@float.js/core 2.0.7 → 2.2.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
@@ -1,5 +1,11 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
+ }) : x)(function(x) {
6
+ if (typeof require !== "undefined") return require.apply(this, arguments);
7
+ throw Error('Dynamic require of "' + x + '" is not supported');
8
+ });
3
9
  var __esm = (fn, res) => function __init() {
4
10
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
11
  };
@@ -729,7 +735,7 @@ function generateAPIResponse(state) {
729
735
  function createDevDashboard(options = {}) {
730
736
  const {
731
737
  enabled = process.env.NODE_ENV !== "production",
732
- path: path7 = "/__float",
738
+ path: path10 = "/__float",
733
739
  auth
734
740
  } = options;
735
741
  if (!enabled) {
@@ -737,7 +743,7 @@ function createDevDashboard(options = {}) {
737
743
  }
738
744
  return (req, res, next) => {
739
745
  const url = req.url || "";
740
- if (!url.startsWith(path7)) {
746
+ if (!url.startsWith(path10)) {
741
747
  return next();
742
748
  }
743
749
  if (auth) {
@@ -756,7 +762,7 @@ function createDevDashboard(options = {}) {
756
762
  return;
757
763
  }
758
764
  }
759
- const subPath = url.slice(path7.length);
765
+ const subPath = url.slice(path10.length);
760
766
  if (subPath === "" || subPath === "/") {
761
767
  res.setHeader("Content-Type", "text/html");
762
768
  res.end(generateDashboardHTML(dashboardState));
@@ -928,6 +934,26 @@ function findLayouts(routePath, allLayouts) {
928
934
  }
929
935
  return layouts;
930
936
  }
937
+ function findLoading(routePath, allLoading) {
938
+ const segments = routePath.split("/").filter(Boolean);
939
+ for (let i = segments.length; i >= 0; i--) {
940
+ const currentPath = i === 0 ? "/" : "/" + segments.slice(0, i).join("/");
941
+ if (allLoading.has(currentPath)) {
942
+ return allLoading.get(currentPath);
943
+ }
944
+ }
945
+ return void 0;
946
+ }
947
+ function findError(routePath, allErrors) {
948
+ const segments = routePath.split("/").filter(Boolean);
949
+ for (let i = segments.length; i >= 0; i--) {
950
+ const currentPath = i === 0 ? "/" : "/" + segments.slice(0, i).join("/");
951
+ if (allErrors.has(currentPath)) {
952
+ return allErrors.get(currentPath);
953
+ }
954
+ }
955
+ return void 0;
956
+ }
931
957
  async function scanRoutes(rootDir, options = {}) {
932
958
  const opts = { ...DEFAULT_OPTIONS, ...options };
933
959
  const appDir = path2.join(rootDir, opts.appDir);
@@ -939,12 +965,20 @@ async function scanRoutes(rootDir, options = {}) {
939
965
  ignore: ["**/node_modules/**", "**/_*/**"]
940
966
  });
941
967
  const layoutMap = /* @__PURE__ */ new Map();
968
+ const loadingMap = /* @__PURE__ */ new Map();
969
+ const errorMap = /* @__PURE__ */ new Map();
942
970
  for (const file of files) {
943
971
  const type = getRouteType(file);
972
+ const { urlPath } = filePathToUrlPath(file, "");
944
973
  if (type === "layout") {
945
- const { urlPath } = filePathToUrlPath(file, "");
946
974
  const layoutPath = urlPath === "/" ? "/" : urlPath.replace(/\/layout$/, "") || "/";
947
975
  layoutMap.set(layoutPath, path2.join(appDir, file));
976
+ } else if (type === "loading") {
977
+ const loadingPath = urlPath === "/" ? "/" : urlPath.replace(/\/loading$/, "") || "/";
978
+ loadingMap.set(loadingPath, path2.join(appDir, file));
979
+ } else if (type === "error") {
980
+ const errorPath = urlPath === "/" ? "/" : urlPath.replace(/\/error$/, "") || "/";
981
+ errorMap.set(errorPath, path2.join(appDir, file));
948
982
  }
949
983
  }
950
984
  const routes = [];
@@ -962,7 +996,9 @@ async function scanRoutes(rootDir, options = {}) {
962
996
  params,
963
997
  isCatchAll,
964
998
  isOptionalCatchAll,
965
- layouts: type === "page" ? findLayouts(urlPath, layoutMap) : []
999
+ layouts: type === "page" ? findLayouts(urlPath, layoutMap) : [],
1000
+ loading: type === "page" ? findLoading(urlPath, loadingMap) : void 0,
1001
+ error: type === "page" ? findError(urlPath, errorMap) : void 0
966
1002
  };
967
1003
  routes.push(route);
968
1004
  }
@@ -1017,9 +1053,9 @@ init_esm_shims();
1017
1053
  // src/server/dev-server.ts
1018
1054
  init_esm_shims();
1019
1055
  import http from "http";
1020
- import fs2 from "fs";
1021
- import path4 from "path";
1022
- import pc from "picocolors";
1056
+ import fs5 from "fs";
1057
+ import path7 from "path";
1058
+ import pc2 from "picocolors";
1023
1059
  import chokidar from "chokidar";
1024
1060
  import { WebSocketServer, WebSocket } from "ws";
1025
1061
  import mime from "mime-types";
@@ -1033,23 +1069,222 @@ import { Writable } from "stream";
1033
1069
  // src/build/transform.ts
1034
1070
  init_esm_shims();
1035
1071
  import * as esbuild from "esbuild";
1072
+ import fs2 from "fs";
1073
+ import path4 from "path";
1074
+ import { pathToFileURL } from "url";
1075
+
1076
+ // src/build/persistent-cache.ts
1077
+ init_esm_shims();
1036
1078
  import fs from "fs";
1037
1079
  import path3 from "path";
1038
- import { pathToFileURL } from "url";
1080
+ import crypto from "crypto";
1081
+ var PersistentCache = class {
1082
+ cacheDir;
1083
+ manifestPath;
1084
+ manifest;
1085
+ constructor(rootDir = process.cwd()) {
1086
+ this.cacheDir = path3.join(rootDir, ".float", "cache");
1087
+ this.manifestPath = path3.join(this.cacheDir, "manifest.json");
1088
+ fs.mkdirSync(this.cacheDir, { recursive: true });
1089
+ this.manifest = this.loadManifest();
1090
+ }
1091
+ loadManifest() {
1092
+ if (fs.existsSync(this.manifestPath)) {
1093
+ try {
1094
+ const data = fs.readFileSync(this.manifestPath, "utf-8");
1095
+ return JSON.parse(data);
1096
+ } catch {
1097
+ }
1098
+ }
1099
+ return {
1100
+ version: "1.0",
1101
+ entries: {}
1102
+ };
1103
+ }
1104
+ saveManifest() {
1105
+ fs.writeFileSync(
1106
+ this.manifestPath,
1107
+ JSON.stringify(this.manifest, null, 2)
1108
+ );
1109
+ }
1110
+ /**
1111
+ * Generate hash for content
1112
+ */
1113
+ hash(content) {
1114
+ return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
1115
+ }
1116
+ /**
1117
+ * Get cache key path
1118
+ */
1119
+ getKeyPath(key) {
1120
+ const safeKey = key.replace(/[^a-z0-9_-]/gi, "_");
1121
+ return path3.join(this.cacheDir, `${safeKey}.cache`);
1122
+ }
1123
+ /**
1124
+ * Check if cache entry is valid
1125
+ */
1126
+ has(key, contentHash) {
1127
+ const entry = this.manifest.entries[key];
1128
+ if (!entry) return false;
1129
+ const cachePath = this.getKeyPath(key);
1130
+ if (!fs.existsSync(cachePath)) {
1131
+ delete this.manifest.entries[key];
1132
+ this.saveManifest();
1133
+ return false;
1134
+ }
1135
+ if (contentHash && entry.hash !== contentHash) {
1136
+ return false;
1137
+ }
1138
+ return true;
1139
+ }
1140
+ /**
1141
+ * Get cached value
1142
+ */
1143
+ get(key) {
1144
+ if (!this.has(key)) return null;
1145
+ try {
1146
+ const cachePath = this.getKeyPath(key);
1147
+ const data = fs.readFileSync(cachePath, "utf-8");
1148
+ const entry = JSON.parse(data);
1149
+ return entry.value;
1150
+ } catch {
1151
+ return null;
1152
+ }
1153
+ }
1154
+ /**
1155
+ * Set cache value
1156
+ */
1157
+ set(key, value, content) {
1158
+ const entry = {
1159
+ key,
1160
+ value,
1161
+ timestamp: Date.now(),
1162
+ hash: content ? this.hash(content) : this.hash(JSON.stringify(value))
1163
+ };
1164
+ const cachePath = this.getKeyPath(key);
1165
+ const data = JSON.stringify(entry);
1166
+ fs.writeFileSync(cachePath, data);
1167
+ this.manifest.entries[key] = {
1168
+ hash: entry.hash,
1169
+ timestamp: entry.timestamp,
1170
+ size: Buffer.byteLength(data)
1171
+ };
1172
+ this.saveManifest();
1173
+ }
1174
+ /**
1175
+ * Delete cache entry
1176
+ */
1177
+ delete(key) {
1178
+ const cachePath = this.getKeyPath(key);
1179
+ if (fs.existsSync(cachePath)) {
1180
+ fs.unlinkSync(cachePath);
1181
+ }
1182
+ if (this.manifest.entries[key]) {
1183
+ delete this.manifest.entries[key];
1184
+ this.saveManifest();
1185
+ return true;
1186
+ }
1187
+ return false;
1188
+ }
1189
+ /**
1190
+ * Clear all cache
1191
+ */
1192
+ clear() {
1193
+ if (fs.existsSync(this.cacheDir)) {
1194
+ fs.rmSync(this.cacheDir, { recursive: true });
1195
+ fs.mkdirSync(this.cacheDir, { recursive: true });
1196
+ }
1197
+ this.manifest = {
1198
+ version: "1.0",
1199
+ entries: {}
1200
+ };
1201
+ this.saveManifest();
1202
+ }
1203
+ /**
1204
+ * Get cache statistics
1205
+ */
1206
+ stats() {
1207
+ const entries = Object.values(this.manifest.entries);
1208
+ const size = entries.reduce((acc, e) => acc + e.size, 0);
1209
+ const timestamps = entries.map((e) => e.timestamp);
1210
+ return {
1211
+ entries: entries.length,
1212
+ size,
1213
+ oldestEntry: timestamps.length > 0 ? Math.min(...timestamps) : null,
1214
+ newestEntry: timestamps.length > 0 ? Math.max(...timestamps) : null
1215
+ };
1216
+ }
1217
+ /**
1218
+ * Clean old entries (older than maxAge milliseconds)
1219
+ */
1220
+ prune(maxAge = 7 * 24 * 60 * 60 * 1e3) {
1221
+ const now = Date.now();
1222
+ let cleaned = 0;
1223
+ for (const [key, entry] of Object.entries(this.manifest.entries)) {
1224
+ if (now - entry.timestamp > maxAge) {
1225
+ this.delete(key);
1226
+ cleaned++;
1227
+ }
1228
+ }
1229
+ return cleaned;
1230
+ }
1231
+ };
1232
+ var globalCache = null;
1233
+ function getCache(rootDir) {
1234
+ if (!globalCache) {
1235
+ globalCache = new PersistentCache(rootDir);
1236
+ }
1237
+ return globalCache;
1238
+ }
1239
+
1240
+ // src/build/transform.ts
1039
1241
  var moduleCache = /* @__PURE__ */ new Map();
1040
- async function transformFile(filePath) {
1041
- const absolutePath = path3.isAbsolute(filePath) ? filePath : path3.resolve(filePath);
1042
- if (!fs.existsSync(absolutePath)) {
1242
+ async function transformFile(filePath, useCache = true) {
1243
+ const absolutePath = path4.isAbsolute(filePath) ? filePath : path4.resolve(filePath);
1244
+ if (!fs2.existsSync(absolutePath)) {
1043
1245
  throw new Error(`File not found: ${absolutePath}`);
1044
1246
  }
1045
- const stats = fs.statSync(absolutePath);
1247
+ const stats = fs2.statSync(absolutePath);
1046
1248
  const mtime = stats.mtimeMs;
1047
1249
  const cached = moduleCache.get(absolutePath);
1048
1250
  if (cached && cached.mtime === mtime) {
1049
1251
  return cached.module;
1050
1252
  }
1051
- const source = fs.readFileSync(absolutePath, "utf-8");
1052
- const ext = path3.extname(absolutePath);
1253
+ if (useCache) {
1254
+ const cache2 = getCache();
1255
+ const source2 = fs2.readFileSync(absolutePath, "utf-8");
1256
+ const sourceHash = __require("crypto").createHash("sha256").update(source2).digest("hex").slice(0, 16);
1257
+ const cacheKey = `transform_${absolutePath}_${sourceHash}`;
1258
+ if (cache2.has(cacheKey)) {
1259
+ const cachedCode = cache2.get(cacheKey);
1260
+ if (cachedCode) {
1261
+ const tempDir2 = path4.join(process.cwd(), ".float", ".cache");
1262
+ fs2.mkdirSync(tempDir2, { recursive: true });
1263
+ const tempFile2 = path4.join(tempDir2, `${path4.basename(absolutePath, path4.extname(absolutePath))}_${Date.now()}.mjs`);
1264
+ fs2.writeFileSync(tempFile2, cachedCode);
1265
+ try {
1266
+ const module = await import(pathToFileURL(tempFile2).href);
1267
+ moduleCache.set(absolutePath, { module, mtime });
1268
+ setImmediate(() => {
1269
+ try {
1270
+ fs2.unlinkSync(tempFile2);
1271
+ } catch {
1272
+ }
1273
+ });
1274
+ return module;
1275
+ } catch (error2) {
1276
+ setImmediate(() => {
1277
+ try {
1278
+ fs2.unlinkSync(tempFile2);
1279
+ } catch {
1280
+ }
1281
+ });
1282
+ }
1283
+ }
1284
+ }
1285
+ }
1286
+ const source = fs2.readFileSync(absolutePath, "utf-8");
1287
+ const ext = path4.extname(absolutePath);
1053
1288
  const loader = getLoader(ext);
1054
1289
  const result = await esbuild.transform(source, {
1055
1290
  loader,
@@ -1059,25 +1294,31 @@ async function transformFile(filePath) {
1059
1294
  sourcemap: "inline",
1060
1295
  sourcefile: absolutePath
1061
1296
  });
1062
- const tempDir = path3.join(process.cwd(), ".float", ".cache");
1063
- fs.mkdirSync(tempDir, { recursive: true });
1064
- const tempFile = path3.join(tempDir, `${path3.basename(absolutePath, ext)}_${Date.now()}.mjs`);
1297
+ const tempDir = path4.join(process.cwd(), ".float", ".cache");
1298
+ fs2.mkdirSync(tempDir, { recursive: true });
1299
+ const tempFile = path4.join(tempDir, `${path4.basename(absolutePath, ext)}_${Date.now()}.mjs`);
1065
1300
  let code = result.code;
1066
- code = rewriteImports(code, path3.dirname(absolutePath));
1067
- fs.writeFileSync(tempFile, code);
1301
+ code = rewriteImports(code, path4.dirname(absolutePath));
1302
+ fs2.writeFileSync(tempFile, code);
1068
1303
  try {
1069
1304
  const module = await import(pathToFileURL(tempFile).href);
1070
1305
  moduleCache.set(absolutePath, { module, mtime });
1306
+ if (useCache) {
1307
+ const cache2 = getCache();
1308
+ const sourceHash = __require("crypto").createHash("sha256").update(source).digest("hex").slice(0, 16);
1309
+ const cacheKey = `transform_${absolutePath}_${sourceHash}`;
1310
+ cache2.set(cacheKey, code, source);
1311
+ }
1071
1312
  setImmediate(() => {
1072
1313
  try {
1073
- fs.unlinkSync(tempFile);
1314
+ fs2.unlinkSync(tempFile);
1074
1315
  } catch {
1075
1316
  }
1076
1317
  });
1077
1318
  return module;
1078
1319
  } catch (error2) {
1079
1320
  try {
1080
- fs.unlinkSync(tempFile);
1321
+ fs2.unlinkSync(tempFile);
1081
1322
  } catch {
1082
1323
  }
1083
1324
  throw error2;
@@ -1106,18 +1347,18 @@ function getLoader(ext) {
1106
1347
  function rewriteImports(code, baseDir) {
1107
1348
  const importRegex = /from\s+['"](\.[^'"]+)['"]/g;
1108
1349
  return code.replace(importRegex, (match, importPath) => {
1109
- let resolvedPath = path3.resolve(baseDir, importPath);
1350
+ let resolvedPath = path4.resolve(baseDir, importPath);
1110
1351
  const extensions = [".tsx", ".ts", ".jsx", ".js", ".mjs", ""];
1111
1352
  let found = false;
1112
1353
  for (const ext of extensions) {
1113
1354
  const tryPath = resolvedPath + ext;
1114
- if (fs.existsSync(tryPath)) {
1355
+ if (fs2.existsSync(tryPath)) {
1115
1356
  resolvedPath = tryPath;
1116
1357
  found = true;
1117
1358
  break;
1118
1359
  }
1119
- const indexPath = path3.join(resolvedPath, `index${ext}`);
1120
- if (fs.existsSync(indexPath)) {
1360
+ const indexPath = path4.join(resolvedPath, `index${ext}`);
1361
+ if (fs2.existsSync(indexPath)) {
1121
1362
  resolvedPath = indexPath;
1122
1363
  found = true;
1123
1364
  break;
@@ -1131,7 +1372,7 @@ function rewriteImports(code, baseDir) {
1131
1372
  }
1132
1373
  function clearModuleCache(filePath) {
1133
1374
  if (filePath) {
1134
- moduleCache.delete(path3.resolve(filePath));
1375
+ moduleCache.delete(path4.resolve(filePath));
1135
1376
  } else {
1136
1377
  moduleCache.clear();
1137
1378
  }
@@ -2520,11 +2761,214 @@ function generateExamplesPage() {
2520
2761
  ` + footer;
2521
2762
  }
2522
2763
 
2764
+ // src/build/css-processor.ts
2765
+ init_esm_shims();
2766
+ import fs4 from "fs";
2767
+ import path6 from "path";
2768
+
2769
+ // src/build/tailwind-setup.ts
2770
+ init_esm_shims();
2771
+ import fs3 from "fs";
2772
+ import path5 from "path";
2773
+ import pc from "picocolors";
2774
+ function checkTailwindSetup(rootDir) {
2775
+ const possibleConfigs = [
2776
+ "tailwind.config.js",
2777
+ "tailwind.config.ts",
2778
+ "tailwind.config.mjs",
2779
+ "tailwind.config.cjs"
2780
+ ];
2781
+ let configPath = null;
2782
+ for (const config of possibleConfigs) {
2783
+ const fullPath = path5.join(rootDir, config);
2784
+ if (fs3.existsSync(fullPath)) {
2785
+ configPath = fullPath;
2786
+ break;
2787
+ }
2788
+ }
2789
+ const globalsPath = path5.join(rootDir, "app", "globals.css");
2790
+ const hasGlobals = fs3.existsSync(globalsPath);
2791
+ return {
2792
+ hasTailwind: !!configPath,
2793
+ configPath,
2794
+ globalsPath: hasGlobals ? globalsPath : null,
2795
+ needsSetup: !configPath || !hasGlobals
2796
+ };
2797
+ }
2798
+ async function setupTailwind(rootDir, options = {}) {
2799
+ const { force = false, silent = false } = options;
2800
+ const config = checkTailwindSetup(rootDir);
2801
+ if (!force && !config.needsSetup) {
2802
+ return;
2803
+ }
2804
+ if (!silent) {
2805
+ console.log(pc.cyan("\n\u{1F3A8} Setting up Tailwind CSS..."));
2806
+ }
2807
+ if (!config.configPath || force) {
2808
+ const tailwindConfig = `/** @type {import('tailwindcss').Config} */
2809
+ export default {
2810
+ content: [
2811
+ './app/**/*.{js,ts,jsx,tsx}',
2812
+ './components/**/*.{js,ts,jsx,tsx}',
2813
+ ],
2814
+ theme: {
2815
+ extend: {},
2816
+ },
2817
+ plugins: [],
2818
+ }
2819
+ `;
2820
+ const configPath = path5.join(rootDir, "tailwind.config.js");
2821
+ fs3.writeFileSync(configPath, tailwindConfig);
2822
+ if (!silent) {
2823
+ console.log(pc.green(" \u2713 Created tailwind.config.js"));
2824
+ }
2825
+ }
2826
+ const postcssPath = path5.join(rootDir, "postcss.config.js");
2827
+ if (!fs3.existsSync(postcssPath) || force) {
2828
+ const postcssConfig = `export default {
2829
+ plugins: {
2830
+ tailwindcss: {},
2831
+ autoprefixer: {},
2832
+ },
2833
+ }
2834
+ `;
2835
+ fs3.writeFileSync(postcssPath, postcssConfig);
2836
+ if (!silent) {
2837
+ console.log(pc.green(" \u2713 Created postcss.config.js"));
2838
+ }
2839
+ }
2840
+ const appDir = path5.join(rootDir, "app");
2841
+ if (!fs3.existsSync(appDir)) {
2842
+ fs3.mkdirSync(appDir, { recursive: true });
2843
+ }
2844
+ const globalsPath = path5.join(appDir, "globals.css");
2845
+ if (!fs3.existsSync(globalsPath) || force) {
2846
+ const globalsCss = `@tailwind base;
2847
+ @tailwind components;
2848
+ @tailwind utilities;
2849
+ `;
2850
+ fs3.writeFileSync(globalsPath, globalsCss);
2851
+ if (!silent) {
2852
+ console.log(pc.green(" \u2713 Created app/globals.css"));
2853
+ }
2854
+ }
2855
+ const layoutPath = path5.join(appDir, "layout.tsx");
2856
+ if (!fs3.existsSync(layoutPath)) {
2857
+ const layoutContent = `import './globals.css'
2858
+
2859
+ export default function RootLayout({
2860
+ children,
2861
+ }: {
2862
+ children: React.ReactNode
2863
+ }) {
2864
+ return (
2865
+ <html lang="en">
2866
+ <body>{children}</body>
2867
+ </html>
2868
+ )
2869
+ }
2870
+ `;
2871
+ fs3.writeFileSync(layoutPath, layoutContent);
2872
+ if (!silent) {
2873
+ console.log(pc.green(" \u2713 Created app/layout.tsx"));
2874
+ }
2875
+ }
2876
+ if (!silent) {
2877
+ console.log(pc.green("\n\u2728 Tailwind CSS ready!\n"));
2878
+ }
2879
+ }
2880
+ function checkTailwindDeps(rootDir) {
2881
+ const packageJsonPath = path5.join(rootDir, "package.json");
2882
+ if (!fs3.existsSync(packageJsonPath)) {
2883
+ return {
2884
+ hasPackageJson: false,
2885
+ hasTailwind: false,
2886
+ hasPostCSS: false,
2887
+ hasAutoprefixer: false
2888
+ };
2889
+ }
2890
+ const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf-8"));
2891
+ const allDeps = {
2892
+ ...packageJson.dependencies,
2893
+ ...packageJson.devDependencies
2894
+ };
2895
+ return {
2896
+ hasPackageJson: true,
2897
+ hasTailwind: !!allDeps["tailwindcss"],
2898
+ hasPostCSS: !!allDeps["postcss"],
2899
+ hasAutoprefixer: !!allDeps["autoprefixer"]
2900
+ };
2901
+ }
2902
+ function getTailwindInstallCommand(rootDir) {
2903
+ const deps = checkTailwindDeps(rootDir);
2904
+ if (!deps.hasPackageJson) {
2905
+ return null;
2906
+ }
2907
+ const missing = [];
2908
+ if (!deps.hasTailwind) missing.push("tailwindcss");
2909
+ if (!deps.hasPostCSS) missing.push("postcss");
2910
+ if (!deps.hasAutoprefixer) missing.push("autoprefixer");
2911
+ if (missing.length === 0) {
2912
+ return null;
2913
+ }
2914
+ const hasYarnLock = fs3.existsSync(path5.join(rootDir, "yarn.lock"));
2915
+ const hasPnpmLock = fs3.existsSync(path5.join(rootDir, "pnpm-lock.yaml"));
2916
+ const hasBunLock = fs3.existsSync(path5.join(rootDir, "bun.lockb"));
2917
+ let pm = "npm install -D";
2918
+ if (hasBunLock) pm = "bun add -d";
2919
+ else if (hasPnpmLock) pm = "pnpm add -D";
2920
+ else if (hasYarnLock) pm = "yarn add -D";
2921
+ return `${pm} ${missing.join(" ")}`;
2922
+ }
2923
+
2924
+ // src/build/css-processor.ts
2925
+ async function processCSS(filePath, rootDir = process.cwd()) {
2926
+ const content = fs4.readFileSync(filePath, "utf-8");
2927
+ const tailwindConfig = checkTailwindSetup(rootDir);
2928
+ if (!tailwindConfig.hasTailwind) {
2929
+ return { code: content };
2930
+ }
2931
+ try {
2932
+ const postcss = await import("postcss").then((m) => m.default);
2933
+ const tailwindcss = await import("tailwindcss").then((m) => m.default);
2934
+ const autoprefixer = await import("autoprefixer").then((m) => m.default);
2935
+ const configPath = tailwindConfig.configPath || path6.join(rootDir, "tailwind.config.js");
2936
+ let tailwindConfigModule = {};
2937
+ if (fs4.existsSync(configPath)) {
2938
+ const configUrl = new URL(`file://${configPath}`);
2939
+ tailwindConfigModule = await import(configUrl.href).then((m) => m.default || m);
2940
+ }
2941
+ const result = await postcss([
2942
+ tailwindcss(tailwindConfigModule),
2943
+ autoprefixer()
2944
+ ]).process(content, {
2945
+ from: filePath,
2946
+ to: filePath,
2947
+ map: { inline: false }
2948
+ });
2949
+ return {
2950
+ code: result.css,
2951
+ map: result.map?.toString()
2952
+ };
2953
+ } catch (error2) {
2954
+ console.warn("CSS processing failed, serving raw CSS:", error2);
2955
+ return { code: content };
2956
+ }
2957
+ }
2958
+ function needsCSSProcessing(filePath, rootDir) {
2959
+ const config = checkTailwindSetup(rootDir);
2960
+ if (!config.hasTailwind) {
2961
+ return false;
2962
+ }
2963
+ const content = fs4.readFileSync(filePath, "utf-8");
2964
+ return content.includes("@tailwind") || content.includes("@apply");
2965
+ }
2966
+
2523
2967
  // src/server/dev-server.ts
2524
2968
  async function createDevServer(options) {
2525
2969
  const { port, host, open } = options;
2526
2970
  const rootDir = process.cwd();
2527
- const publicDir = path4.join(rootDir, "public");
2971
+ const publicDir = path7.join(rootDir, "public");
2528
2972
  let routes = [];
2529
2973
  let server = null;
2530
2974
  let wss = null;
@@ -2532,9 +2976,20 @@ async function createDevServer(options) {
2532
2976
  async function refreshRoutes() {
2533
2977
  try {
2534
2978
  routes = await scanRoutes(rootDir);
2535
- console.log(pc.dim(` \u{1F4C1} Found ${routes.length} routes`));
2979
+ console.log(pc2.dim(` \u{1F4C1} Found ${routes.length} routes`));
2980
+ const tailwindConfig = checkTailwindSetup(rootDir);
2981
+ if (tailwindConfig.needsSetup) {
2982
+ console.log(pc2.yellow(" \u26A0\uFE0F Tailwind not configured"));
2983
+ const installCmd = getTailwindInstallCommand(rootDir);
2984
+ if (installCmd) {
2985
+ console.log(pc2.dim(` \u{1F4A1} Run: ${installCmd}`));
2986
+ console.log(pc2.dim(` \u{1F4A1} Then: npx float dev`));
2987
+ } else {
2988
+ await setupTailwind(rootDir);
2989
+ }
2990
+ }
2536
2991
  } catch (error2) {
2537
- console.error(pc.red("Failed to scan routes:"), error2);
2992
+ console.error(pc2.red("Failed to scan routes:"), error2);
2538
2993
  }
2539
2994
  }
2540
2995
  function notifyClients(type, data) {
@@ -2595,16 +3050,46 @@ ${FLOAT_ERROR_OVERLAY}
2595
3050
  async function handleRequest(req, res) {
2596
3051
  const url = new URL(req.url || "/", `http://${host}:${port}`);
2597
3052
  const pathname = url.pathname;
2598
- console.log(pc.dim(` ${req.method} ${pathname}`));
3053
+ console.log(pc2.dim(` ${req.method} ${pathname}`));
2599
3054
  try {
2600
- const publicFilePath = path4.join(publicDir, pathname);
2601
- if (fs2.existsSync(publicFilePath) && fs2.statSync(publicFilePath).isFile()) {
2602
- const content = fs2.readFileSync(publicFilePath);
3055
+ const publicFilePath = path7.join(publicDir, pathname);
3056
+ if (fs5.existsSync(publicFilePath) && fs5.statSync(publicFilePath).isFile()) {
3057
+ const content = fs5.readFileSync(publicFilePath);
2603
3058
  const contentType = mime.lookup(publicFilePath) || "application/octet-stream";
2604
3059
  res.writeHead(200, { "Content-Type": contentType });
2605
3060
  res.end(content);
2606
3061
  return;
2607
3062
  }
3063
+ if (pathname.endsWith(".css")) {
3064
+ const cssPath = path7.join(rootDir, "app", pathname.replace(/^\//, ""));
3065
+ if (fs5.existsSync(cssPath)) {
3066
+ try {
3067
+ const needsProcessing = needsCSSProcessing(cssPath, rootDir);
3068
+ if (needsProcessing) {
3069
+ const result = await processCSS(cssPath, rootDir);
3070
+ res.writeHead(200, {
3071
+ "Content-Type": "text/css",
3072
+ "Cache-Control": "no-cache"
3073
+ });
3074
+ res.end(result.code);
3075
+ } else {
3076
+ const content = fs5.readFileSync(cssPath, "utf-8");
3077
+ res.writeHead(200, {
3078
+ "Content-Type": "text/css",
3079
+ "Cache-Control": "no-cache"
3080
+ });
3081
+ res.end(content);
3082
+ }
3083
+ return;
3084
+ } catch (error2) {
3085
+ console.error(pc2.red("CSS processing error:"), error2);
3086
+ const content = fs5.readFileSync(cssPath, "utf-8");
3087
+ res.writeHead(200, { "Content-Type": "text/css" });
3088
+ res.end(content);
3089
+ return;
3090
+ }
3091
+ }
3092
+ }
2608
3093
  if (pathname.startsWith("/_float/")) {
2609
3094
  res.writeHead(200, { "Content-Type": "application/javascript" });
2610
3095
  res.end("// Float.js internal asset");
@@ -2669,7 +3154,7 @@ ${FLOAT_ERROR_OVERLAY}
2669
3154
  });
2670
3155
  res.end(html);
2671
3156
  } catch (error2) {
2672
- console.error(pc.red("Request error:"), error2);
3157
+ console.error(pc2.red("Request error:"), error2);
2673
3158
  res.writeHead(500, { "Content-Type": "text/html" });
2674
3159
  res.end(createErrorPage(error2));
2675
3160
  }
@@ -2698,7 +3183,7 @@ ${FLOAT_ERROR_OVERLAY}
2698
3183
  const responseBody = await response.text();
2699
3184
  res.end(responseBody);
2700
3185
  } catch (error2) {
2701
- console.error(pc.red("API route error:"), error2);
3186
+ console.error(pc2.red("API route error:"), error2);
2702
3187
  res.writeHead(500, { "Content-Type": "application/json" });
2703
3188
  res.end(JSON.stringify({ error: "Internal server error" }));
2704
3189
  }
@@ -2713,9 +3198,9 @@ ${FLOAT_ERROR_OVERLAY}
2713
3198
  });
2714
3199
  const watcher = chokidar.watch(
2715
3200
  [
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}")
3201
+ path7.join(rootDir, "app/**/*.{ts,tsx,js,jsx}"),
3202
+ path7.join(rootDir, "components/**/*.{ts,tsx,js,jsx}"),
3203
+ path7.join(rootDir, "lib/**/*.{ts,tsx,js,jsx}")
2719
3204
  ],
2720
3205
  {
2721
3206
  ignored: /node_modules/,
@@ -2723,8 +3208,8 @@ ${FLOAT_ERROR_OVERLAY}
2723
3208
  }
2724
3209
  );
2725
3210
  watcher.on("change", async (filePath) => {
2726
- console.log(pc.yellow(`
2727
- \u26A1 File changed: ${path4.relative(rootDir, filePath)}`));
3211
+ console.log(pc2.yellow(`
3212
+ \u26A1 File changed: ${path7.relative(rootDir, filePath)}`));
2728
3213
  if (filePath.includes("/app/")) {
2729
3214
  await refreshRoutes();
2730
3215
  }
@@ -2732,31 +3217,31 @@ ${FLOAT_ERROR_OVERLAY}
2732
3217
  });
2733
3218
  watcher.on("add", async (filePath) => {
2734
3219
  if (filePath.includes("/app/")) {
2735
- console.log(pc.green(`
2736
- \u2795 File added: ${path4.relative(rootDir, filePath)}`));
3220
+ console.log(pc2.green(`
3221
+ \u2795 File added: ${path7.relative(rootDir, filePath)}`));
2737
3222
  await refreshRoutes();
2738
3223
  notifyClients("reload");
2739
3224
  }
2740
3225
  });
2741
3226
  watcher.on("unlink", async (filePath) => {
2742
3227
  if (filePath.includes("/app/")) {
2743
- console.log(pc.red(`
2744
- \u2796 File removed: ${path4.relative(rootDir, filePath)}`));
3228
+ console.log(pc2.red(`
3229
+ \u2796 File removed: ${path7.relative(rootDir, filePath)}`));
2745
3230
  await refreshRoutes();
2746
3231
  notifyClients("reload");
2747
3232
  }
2748
3233
  });
2749
3234
  return new Promise((resolve, reject) => {
2750
3235
  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}
3236
+ console.log(pc2.green(` \u2705 Server running at ${pc2.cyan(`http://${host}:${port}`)}`));
3237
+ console.log(pc2.dim(` \u26A1 HMR enabled on ws://${host}:${port + 1}
2753
3238
  `));
2754
- console.log(pc.bold(" Routes:"));
3239
+ console.log(pc2.bold(" Routes:"));
2755
3240
  routes.forEach((route) => {
2756
3241
  if (route.type === "page") {
2757
- console.log(pc.dim(` ${pc.green("\u25CF")} ${route.path}`));
3242
+ console.log(pc2.dim(` ${pc2.green("\u25CF")} ${route.path}`));
2758
3243
  } else if (route.type === "api") {
2759
- console.log(pc.dim(` ${pc.blue("\u25C6")} ${route.path} (API)`));
3244
+ console.log(pc2.dim(` ${pc2.blue("\u25C6")} ${route.path} (API)`));
2760
3245
  }
2761
3246
  });
2762
3247
  console.log("");
@@ -2876,45 +3361,45 @@ function escapeHtml2(text) {
2876
3361
  // src/server/prod-server.ts
2877
3362
  init_esm_shims();
2878
3363
  import http2 from "http";
2879
- import fs3 from "fs";
2880
- import path5 from "path";
2881
- import pc2 from "picocolors";
3364
+ import fs6 from "fs";
3365
+ import path8 from "path";
3366
+ import pc3 from "picocolors";
2882
3367
  import mime2 from "mime-types";
2883
3368
  var cachedRoutes = [];
2884
3369
  var pageCache = /* @__PURE__ */ new Map();
2885
3370
  async function startProductionServer(options) {
2886
3371
  const { port, host } = options;
2887
3372
  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"));
3373
+ const distDir = path8.join(rootDir, ".float");
3374
+ const publicDir = path8.join(rootDir, "public");
3375
+ const manifestPath = path8.join(distDir, "routes-manifest.json");
3376
+ if (fs6.existsSync(manifestPath)) {
3377
+ const manifest = JSON.parse(fs6.readFileSync(manifestPath, "utf-8"));
2893
3378
  cachedRoutes = manifest.routes;
2894
- console.log(pc2.dim(` \u{1F4E6} Loaded ${cachedRoutes.length} routes from manifest`));
3379
+ console.log(pc3.dim(` \u{1F4E6} Loaded ${cachedRoutes.length} routes from manifest`));
2895
3380
  } else {
2896
- console.error(pc2.red(" \u274C No build manifest found. Run `float build` first."));
3381
+ console.error(pc3.red(" \u274C No build manifest found. Run `float build` first."));
2897
3382
  process.exit(1);
2898
3383
  }
2899
- const pagesDir = path5.join(distDir, "pages");
2900
- if (fs3.existsSync(pagesDir)) {
2901
- const prerenderedFiles = fs3.readdirSync(pagesDir, { recursive: true });
3384
+ const pagesDir = path8.join(distDir, "pages");
3385
+ if (fs6.existsSync(pagesDir)) {
3386
+ const prerenderedFiles = fs6.readdirSync(pagesDir, { recursive: true });
2902
3387
  for (const file of prerenderedFiles) {
2903
3388
  if (file.endsWith(".html")) {
2904
3389
  const routePath = "/" + file.replace(/\.html$/, "").replace(/index$/, "");
2905
- const content = fs3.readFileSync(path5.join(pagesDir, file), "utf-8");
3390
+ const content = fs6.readFileSync(path8.join(pagesDir, file), "utf-8");
2906
3391
  pageCache.set(routePath, content);
2907
3392
  }
2908
3393
  }
2909
- console.log(pc2.dim(` \u{1F4C4} Loaded ${pageCache.size} pre-rendered pages`));
3394
+ console.log(pc3.dim(` \u{1F4C4} Loaded ${pageCache.size} pre-rendered pages`));
2910
3395
  }
2911
3396
  const server = http2.createServer(async (req, res) => {
2912
3397
  const url = new URL(req.url || "/", `http://${host}:${port}`);
2913
3398
  const pathname = url.pathname;
2914
3399
  try {
2915
- const staticPath = path5.join(distDir, "static", pathname);
2916
- if (fs3.existsSync(staticPath) && fs3.statSync(staticPath).isFile()) {
2917
- const content = fs3.readFileSync(staticPath);
3400
+ const staticPath = path8.join(distDir, "static", pathname);
3401
+ if (fs6.existsSync(staticPath) && fs6.statSync(staticPath).isFile()) {
3402
+ const content = fs6.readFileSync(staticPath);
2918
3403
  const contentType = mime2.lookup(staticPath) || "application/octet-stream";
2919
3404
  res.writeHead(200, {
2920
3405
  "Content-Type": contentType,
@@ -2923,9 +3408,9 @@ async function startProductionServer(options) {
2923
3408
  res.end(content);
2924
3409
  return;
2925
3410
  }
2926
- const publicFilePath = path5.join(publicDir, pathname);
2927
- if (fs3.existsSync(publicFilePath) && fs3.statSync(publicFilePath).isFile()) {
2928
- const content = fs3.readFileSync(publicFilePath);
3411
+ const publicFilePath = path8.join(publicDir, pathname);
3412
+ if (fs6.existsSync(publicFilePath) && fs6.statSync(publicFilePath).isFile()) {
3413
+ const content = fs6.readFileSync(publicFilePath);
2929
3414
  const contentType = mime2.lookup(publicFilePath) || "application/octet-stream";
2930
3415
  res.writeHead(200, { "Content-Type": contentType });
2931
3416
  res.end(content);
@@ -2958,13 +3443,13 @@ async function startProductionServer(options) {
2958
3443
  });
2959
3444
  res.end(html);
2960
3445
  } catch (error2) {
2961
- console.error(pc2.red("Request error:"), error2);
3446
+ console.error(pc3.red("Request error:"), error2);
2962
3447
  res.writeHead(500, { "Content-Type": "text/html" });
2963
3448
  res.end("<h1>500 - Internal Server Error</h1>");
2964
3449
  }
2965
3450
  });
2966
3451
  server.listen(port, host, () => {
2967
- console.log(pc2.green(` \u2705 Production server running at ${pc2.cyan(`http://${host}:${port}`)}
3452
+ console.log(pc3.green(` \u2705 Production server running at ${pc3.cyan(`http://${host}:${port}`)}
2968
3453
  `));
2969
3454
  });
2970
3455
  }
@@ -2972,9 +3457,9 @@ async function startProductionServer(options) {
2972
3457
  // src/build/index.ts
2973
3458
  init_esm_shims();
2974
3459
  import * as esbuild2 from "esbuild";
2975
- import fs4 from "fs";
2976
- import path6 from "path";
2977
- import pc3 from "picocolors";
3460
+ import fs7 from "fs";
3461
+ import path9 from "path";
3462
+ import pc4 from "picocolors";
2978
3463
  var DEFAULT_BUILD_OPTIONS = {
2979
3464
  analyze: false,
2980
3465
  minify: true,
@@ -2984,27 +3469,27 @@ async function build2(options = {}) {
2984
3469
  const opts = { ...DEFAULT_BUILD_OPTIONS, ...options };
2985
3470
  const startTime = Date.now();
2986
3471
  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..."));
3472
+ const outputDir = path9.join(rootDir, ".float");
3473
+ if (fs7.existsSync(outputDir)) {
3474
+ fs7.rmSync(outputDir, { recursive: true });
3475
+ }
3476
+ fs7.mkdirSync(outputDir, { recursive: true });
3477
+ fs7.mkdirSync(path9.join(outputDir, "pages"), { recursive: true });
3478
+ fs7.mkdirSync(path9.join(outputDir, "static"), { recursive: true });
3479
+ fs7.mkdirSync(path9.join(outputDir, "server"), { recursive: true });
3480
+ console.log(pc4.dim(" Scanning routes..."));
2996
3481
  const routes = await scanRoutes(rootDir);
2997
3482
  const pageRoutes = routes.filter((r) => r.type === "page" && !r.params.length);
2998
3483
  const dynamicRoutes = routes.filter((r) => r.type === "page" && r.params.length > 0);
2999
3484
  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..."));
3485
+ console.log(pc4.dim(` Found ${pageRoutes.length} static pages, ${dynamicRoutes.length} dynamic routes, ${apiRoutes.length} API routes`));
3486
+ console.log(pc4.dim(" Building client bundle..."));
3002
3487
  const clientEntryPoints = routes.filter((r) => r.type === "page").map((r) => r.absolutePath);
3003
3488
  if (clientEntryPoints.length > 0) {
3004
3489
  await esbuild2.build({
3005
3490
  entryPoints: clientEntryPoints,
3006
3491
  bundle: true,
3007
- outdir: path6.join(outputDir, "static", "_float"),
3492
+ outdir: path9.join(outputDir, "static", "_float"),
3008
3493
  format: "esm",
3009
3494
  splitting: true,
3010
3495
  minify: opts.minify,
@@ -3026,13 +3511,13 @@ async function build2(options = {}) {
3026
3511
  metafile: opts.analyze
3027
3512
  });
3028
3513
  }
3029
- console.log(pc3.dim(" Building server bundle..."));
3514
+ console.log(pc4.dim(" Building server bundle..."));
3030
3515
  const serverEntryPoints = routes.map((r) => r.absolutePath);
3031
3516
  if (serverEntryPoints.length > 0) {
3032
3517
  await esbuild2.build({
3033
3518
  entryPoints: serverEntryPoints,
3034
3519
  bundle: true,
3035
- outdir: path6.join(outputDir, "server"),
3520
+ outdir: path9.join(outputDir, "server"),
3036
3521
  format: "esm",
3037
3522
  platform: "node",
3038
3523
  target: ["node18"],
@@ -3049,26 +3534,26 @@ async function build2(options = {}) {
3049
3534
  external: ["react", "react-dom", "@float/core"]
3050
3535
  });
3051
3536
  }
3052
- console.log(pc3.dim(" Pre-rendering static pages..."));
3537
+ console.log(pc4.dim(" Pre-rendering static pages..."));
3053
3538
  const prerenderedPages = [];
3054
3539
  for (const route of pageRoutes) {
3055
3540
  try {
3056
3541
  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);
3542
+ const outputPath = route.path === "/" ? path9.join(outputDir, "pages", "index.html") : path9.join(outputDir, "pages", route.path, "index.html");
3543
+ fs7.mkdirSync(path9.dirname(outputPath), { recursive: true });
3544
+ fs7.writeFileSync(outputPath, html);
3060
3545
  prerenderedPages.push(route.path);
3061
- console.log(pc3.dim(` \u2713 ${route.path}`));
3546
+ console.log(pc4.dim(` \u2713 ${route.path}`));
3062
3547
  } catch (error2) {
3063
- console.log(pc3.yellow(` \u26A0 ${route.path} (will render at runtime)`));
3548
+ console.log(pc4.yellow(` \u26A0 ${route.path} (will render at runtime)`));
3064
3549
  }
3065
3550
  }
3066
- console.log(pc3.dim(" Building API routes..."));
3551
+ console.log(pc4.dim(" Building API routes..."));
3067
3552
  for (const route of apiRoutes) {
3068
3553
  await esbuild2.build({
3069
3554
  entryPoints: [route.absolutePath],
3070
3555
  bundle: true,
3071
- outfile: path6.join(outputDir, "server", "api", `${route.path.replace(/\//g, "_")}.js`),
3556
+ outfile: path9.join(outputDir, "server", "api", `${route.path.replace(/\//g, "_")}.js`),
3072
3557
  format: "esm",
3073
3558
  platform: "neutral",
3074
3559
  // Edge compatible
@@ -3076,10 +3561,10 @@ async function build2(options = {}) {
3076
3561
  minify: true
3077
3562
  });
3078
3563
  }
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"));
3564
+ const publicDir = path9.join(rootDir, "public");
3565
+ if (fs7.existsSync(publicDir)) {
3566
+ console.log(pc4.dim(" Copying public assets..."));
3567
+ copyDir(publicDir, path9.join(outputDir, "static"));
3083
3568
  }
3084
3569
  const manifest = {
3085
3570
  version: 1,
@@ -3088,19 +3573,19 @@ async function build2(options = {}) {
3088
3573
  path: r.path,
3089
3574
  type: r.type,
3090
3575
  filePath: r.filePath,
3091
- absolutePath: path6.relative(rootDir, r.absolutePath),
3576
+ absolutePath: path9.relative(rootDir, r.absolutePath),
3092
3577
  params: r.params,
3093
3578
  isCatchAll: r.isCatchAll,
3094
3579
  isOptionalCatchAll: r.isOptionalCatchAll,
3095
- layouts: r.layouts.map((l) => path6.relative(rootDir, l)),
3580
+ layouts: r.layouts.map((l) => path9.relative(rootDir, l)),
3096
3581
  prerendered: prerenderedPages.includes(r.path)
3097
3582
  })),
3098
3583
  staticPages: prerenderedPages,
3099
3584
  dynamicRoutes: dynamicRoutes.map((r) => r.path),
3100
3585
  apiRoutes: apiRoutes.map((r) => r.path)
3101
3586
  };
3102
- fs4.writeFileSync(
3103
- path6.join(outputDir, "routes-manifest.json"),
3587
+ fs7.writeFileSync(
3588
+ path9.join(outputDir, "routes-manifest.json"),
3104
3589
  JSON.stringify(manifest, null, 2)
3105
3590
  );
3106
3591
  const duration = Date.now() - startTime;
@@ -3110,16 +3595,16 @@ async function build2(options = {}) {
3110
3595
  routes: routes.length,
3111
3596
  pages: prerenderedPages.length
3112
3597
  };
3113
- fs4.writeFileSync(
3114
- path6.join(outputDir, "build-info.json"),
3598
+ fs7.writeFileSync(
3599
+ path9.join(outputDir, "build-info.json"),
3115
3600
  JSON.stringify(buildInfo, null, 2)
3116
3601
  );
3117
3602
  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/`));
3603
+ console.log(pc4.bold(" Build Summary:"));
3604
+ console.log(pc4.dim(` Static Pages: ${prerenderedPages.length}`));
3605
+ console.log(pc4.dim(` Dynamic Routes: ${dynamicRoutes.length}`));
3606
+ console.log(pc4.dim(` API Routes: ${apiRoutes.length}`));
3607
+ console.log(pc4.dim(` Output: .float/`));
3123
3608
  return {
3124
3609
  routes,
3125
3610
  duration,
@@ -3129,15 +3614,15 @@ async function build2(options = {}) {
3129
3614
  };
3130
3615
  }
3131
3616
  function copyDir(src, dest) {
3132
- fs4.mkdirSync(dest, { recursive: true });
3133
- const entries = fs4.readdirSync(src, { withFileTypes: true });
3617
+ fs7.mkdirSync(dest, { recursive: true });
3618
+ const entries = fs7.readdirSync(src, { withFileTypes: true });
3134
3619
  for (const entry of entries) {
3135
- const srcPath = path6.join(src, entry.name);
3136
- const destPath = path6.join(dest, entry.name);
3620
+ const srcPath = path9.join(src, entry.name);
3621
+ const destPath = path9.join(dest, entry.name);
3137
3622
  if (entry.isDirectory()) {
3138
3623
  copyDir(srcPath, destPath);
3139
3624
  } else {
3140
- fs4.copyFileSync(srcPath, destPath);
3625
+ fs7.copyFileSync(srcPath, destPath);
3141
3626
  }
3142
3627
  }
3143
3628
  }
@@ -5590,10 +6075,10 @@ function matcherToRegex(pattern) {
5590
6075
  let regex = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, "(?<$1>[^/]+)").replace(/\\\*/g, ".*").replace(/\\\(([^)]+)\\\)/g, "($1)?");
5591
6076
  return new RegExp(`^${regex}$`);
5592
6077
  }
5593
- function matchesPath(path7, matcher) {
6078
+ function matchesPath(path10, matcher) {
5594
6079
  if (!matcher) return true;
5595
6080
  const patterns = Array.isArray(matcher) ? matcher : [matcher];
5596
- return patterns.some((pattern) => matcherToRegex(pattern).test(path7));
6081
+ return patterns.some((pattern) => matcherToRegex(pattern).test(path10));
5597
6082
  }
5598
6083
  function parseCookies(cookieHeader) {
5599
6084
  const cookies = /* @__PURE__ */ new Map();
@@ -5839,14 +6324,14 @@ var middlewareHelpers = {
5839
6324
  */
5840
6325
  trailingSlash(add = false) {
5841
6326
  return (req) => {
5842
- const path7 = req.nextUrl.pathname;
5843
- if (path7 === "/") return NextResponse.next();
5844
- const hasSlash = path7.endsWith("/");
6327
+ const path10 = req.nextUrl.pathname;
6328
+ if (path10 === "/") return NextResponse.next();
6329
+ const hasSlash = path10.endsWith("/");
5845
6330
  if (add && !hasSlash) {
5846
- return NextResponse.redirect(new URL(path7 + "/", req.request.url));
6331
+ return NextResponse.redirect(new URL(path10 + "/", req.request.url));
5847
6332
  }
5848
6333
  if (!add && hasSlash) {
5849
- return NextResponse.redirect(new URL(path7.slice(0, -1), req.request.url));
6334
+ return NextResponse.redirect(new URL(path10.slice(0, -1), req.request.url));
5850
6335
  }
5851
6336
  return NextResponse.next();
5852
6337
  };
@@ -5884,8 +6369,8 @@ var SSGEngine = class {
5884
6369
  mkdirSync2(this.diskCachePath, { recursive: true });
5885
6370
  }
5886
6371
  }
5887
- getCacheKey(path7, locale) {
5888
- const normalized = path7.replace(/^\/+|\/+$/g, "") || "index";
6372
+ getCacheKey(path10, locale) {
6373
+ const normalized = path10.replace(/^\/+|\/+$/g, "") || "index";
5889
6374
  const key = locale ? `${locale}/${normalized}` : normalized;
5890
6375
  return key.replace(/\//g, "__");
5891
6376
  }
@@ -5898,9 +6383,9 @@ var SSGEngine = class {
5898
6383
  /**
5899
6384
  * Generate static page and cache it
5900
6385
  */
5901
- async generatePage(path7, getStaticProps, render, params = {}, locale) {
6386
+ async generatePage(path10, getStaticProps, render, params = {}, locale) {
5902
6387
  const startTime = Date.now();
5903
- const cacheKey = this.getCacheKey(path7, locale);
6388
+ const cacheKey = this.getCacheKey(path10, locale);
5904
6389
  try {
5905
6390
  const propsResult = await getStaticProps({
5906
6391
  params,
@@ -5909,7 +6394,7 @@ var SSGEngine = class {
5909
6394
  });
5910
6395
  if (propsResult.redirect) {
5911
6396
  return {
5912
- path: path7,
6397
+ path: path10,
5913
6398
  success: true,
5914
6399
  duration: Date.now() - startTime,
5915
6400
  size: 0
@@ -5917,7 +6402,7 @@ var SSGEngine = class {
5917
6402
  }
5918
6403
  if (propsResult.notFound) {
5919
6404
  return {
5920
- path: path7,
6405
+ path: path10,
5921
6406
  success: false,
5922
6407
  duration: Date.now() - startTime,
5923
6408
  size: 0,
@@ -5941,7 +6426,7 @@ var SSGEngine = class {
5941
6426
  this.setMemoryCache(cacheKey, cachedPage);
5942
6427
  this.writeToDisk(cacheKey, cachedPage);
5943
6428
  return {
5944
- path: path7,
6429
+ path: path10,
5945
6430
  success: true,
5946
6431
  duration: Date.now() - startTime,
5947
6432
  size: html.length,
@@ -5949,7 +6434,7 @@ var SSGEngine = class {
5949
6434
  };
5950
6435
  } catch (error2) {
5951
6436
  return {
5952
- path: path7,
6437
+ path: path10,
5953
6438
  success: false,
5954
6439
  duration: Date.now() - startTime,
5955
6440
  size: 0,
@@ -5960,8 +6445,8 @@ var SSGEngine = class {
5960
6445
  /**
5961
6446
  * Get cached page or generate on-demand
5962
6447
  */
5963
- async getPage(path7, getStaticProps, render, params = {}, locale, fallback = false) {
5964
- const cacheKey = this.getCacheKey(path7, locale);
6448
+ async getPage(path10, getStaticProps, render, params = {}, locale, fallback = false) {
6449
+ const cacheKey = this.getCacheKey(path10, locale);
5965
6450
  let cached = this.memoryCache.get(cacheKey);
5966
6451
  if (!cached) {
5967
6452
  cached = this.readFromDisk(cacheKey) || void 0;
@@ -5972,7 +6457,7 @@ var SSGEngine = class {
5972
6457
  if (cached) {
5973
6458
  const isStale = cached.revalidateAfter !== null && Date.now() > cached.revalidateAfter;
5974
6459
  if (isStale && this.config.staleWhileRevalidate) {
5975
- this.triggerRevalidation(path7, getStaticProps, render, params, locale);
6460
+ this.triggerRevalidation(path10, getStaticProps, render, params, locale);
5976
6461
  }
5977
6462
  return { cached, stale: isStale };
5978
6463
  }
@@ -5980,7 +6465,7 @@ var SSGEngine = class {
5980
6465
  return null;
5981
6466
  }
5982
6467
  if (fallback === "blocking") {
5983
- const result = await this.generatePage(path7, getStaticProps, render, params, locale);
6468
+ const result = await this.generatePage(path10, getStaticProps, render, params, locale);
5984
6469
  if (result.success) {
5985
6470
  const newCached = this.memoryCache.get(cacheKey);
5986
6471
  return newCached ? { cached: newCached, stale: false } : null;
@@ -5991,14 +6476,14 @@ var SSGEngine = class {
5991
6476
  /**
5992
6477
  * Trigger ISR revalidation in background
5993
6478
  */
5994
- async triggerRevalidation(path7, getStaticProps, render, params = {}, locale) {
5995
- const cacheKey = this.getCacheKey(path7, locale);
6479
+ async triggerRevalidation(path10, getStaticProps, render, params = {}, locale) {
6480
+ const cacheKey = this.getCacheKey(path10, locale);
5996
6481
  if (this.isrState.revalidating.has(cacheKey)) {
5997
6482
  return;
5998
6483
  }
5999
6484
  this.isrState.revalidating.add(cacheKey);
6000
6485
  try {
6001
- await this.generatePage(path7, getStaticProps, render, params, locale);
6486
+ await this.generatePage(path10, getStaticProps, render, params, locale);
6002
6487
  this.isrState.lastRevalidation.set(cacheKey, Date.now());
6003
6488
  } finally {
6004
6489
  this.isrState.revalidating.delete(cacheKey);
@@ -6007,9 +6492,9 @@ var SSGEngine = class {
6007
6492
  /**
6008
6493
  * Force revalidation of a path (On-Demand ISR)
6009
6494
  */
6010
- async revalidate(path7, getStaticProps, render, params = {}, locale) {
6495
+ async revalidate(path10, getStaticProps, render, params = {}, locale) {
6011
6496
  try {
6012
- const result = await this.generatePage(path7, getStaticProps, render, params, locale);
6497
+ const result = await this.generatePage(path10, getStaticProps, render, params, locale);
6013
6498
  return { revalidated: result.success, error: result.error?.message };
6014
6499
  } catch (error2) {
6015
6500
  return {
@@ -6172,10 +6657,10 @@ function createSSGHandler(options) {
6172
6657
  const engine = getSSGEngine();
6173
6658
  return async (req) => {
6174
6659
  const url = new URL(req.url);
6175
- const path7 = url.pathname;
6660
+ const path10 = url.pathname;
6176
6661
  const params = {};
6177
6662
  const result = await engine.getPage(
6178
- path7,
6663
+ path10,
6179
6664
  options.getStaticProps,
6180
6665
  options.render,
6181
6666
  params,
@@ -6542,7 +7027,7 @@ var AnalyticsEngine = class {
6542
7027
  for (const pv of recentPageviews) {
6543
7028
  pathCounts[pv.pathname] = (pathCounts[pv.pathname] || 0) + 1;
6544
7029
  }
6545
- const topPages = Object.entries(pathCounts).map(([path7, count]) => ({ path: path7, count })).sort((a, b) => b.count - a.count).slice(0, 10);
7030
+ const topPages = Object.entries(pathCounts).map(([path10, count]) => ({ path: path10, count })).sort((a, b) => b.count - a.count).slice(0, 10);
6546
7031
  return {
6547
7032
  activeUsers: activeSessions.size,
6548
7033
  pageviews: recentPageviews.length,