@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/cli/index.js CHANGED
@@ -1,6 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
+ }) : x)(function(x) {
7
+ if (typeof require !== "undefined") return require.apply(this, arguments);
8
+ throw Error('Dynamic require of "' + x + '" is not supported');
9
+ });
4
10
  var __esm = (fn, res) => function __init() {
5
11
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
12
  };
@@ -730,7 +736,7 @@ function generateAPIResponse(state) {
730
736
  function createDevDashboard(options = {}) {
731
737
  const {
732
738
  enabled = process.env.NODE_ENV !== "production",
733
- path: path7 = "/__float",
739
+ path: path10 = "/__float",
734
740
  auth
735
741
  } = options;
736
742
  if (!enabled) {
@@ -738,7 +744,7 @@ function createDevDashboard(options = {}) {
738
744
  }
739
745
  return (req, res, next) => {
740
746
  const url = req.url || "";
741
- if (!url.startsWith(path7)) {
747
+ if (!url.startsWith(path10)) {
742
748
  return next();
743
749
  }
744
750
  if (auth) {
@@ -757,7 +763,7 @@ function createDevDashboard(options = {}) {
757
763
  return;
758
764
  }
759
765
  }
760
- const subPath = url.slice(path7.length);
766
+ const subPath = url.slice(path10.length);
761
767
  if (subPath === "" || subPath === "/") {
762
768
  res.setHeader("Content-Type", "text/html");
763
769
  res.end(generateDashboardHTML(dashboardState));
@@ -868,14 +874,14 @@ var init_devtools = __esm({
868
874
  // src/cli/index.ts
869
875
  init_esm_shims();
870
876
  import { cac } from "cac";
871
- import pc4 from "picocolors";
877
+ import pc5 from "picocolors";
872
878
 
873
879
  // src/server/dev-server.ts
874
880
  init_esm_shims();
875
881
  import http from "http";
876
- import fs2 from "fs";
877
- import path4 from "path";
878
- import pc from "picocolors";
882
+ import fs5 from "fs";
883
+ import path7 from "path";
884
+ import pc2 from "picocolors";
879
885
  import chokidar from "chokidar";
880
886
  import { WebSocketServer, WebSocket } from "ws";
881
887
  import mime from "mime-types";
@@ -937,6 +943,26 @@ function findLayouts(routePath, allLayouts) {
937
943
  }
938
944
  return layouts;
939
945
  }
946
+ function findLoading(routePath, allLoading) {
947
+ const segments = routePath.split("/").filter(Boolean);
948
+ for (let i = segments.length; i >= 0; i--) {
949
+ const currentPath = i === 0 ? "/" : "/" + segments.slice(0, i).join("/");
950
+ if (allLoading.has(currentPath)) {
951
+ return allLoading.get(currentPath);
952
+ }
953
+ }
954
+ return void 0;
955
+ }
956
+ function findError(routePath, allErrors) {
957
+ const segments = routePath.split("/").filter(Boolean);
958
+ for (let i = segments.length; i >= 0; i--) {
959
+ const currentPath = i === 0 ? "/" : "/" + segments.slice(0, i).join("/");
960
+ if (allErrors.has(currentPath)) {
961
+ return allErrors.get(currentPath);
962
+ }
963
+ }
964
+ return void 0;
965
+ }
940
966
  async function scanRoutes(rootDir, options = {}) {
941
967
  const opts = { ...DEFAULT_OPTIONS, ...options };
942
968
  const appDir = path2.join(rootDir, opts.appDir);
@@ -948,12 +974,20 @@ async function scanRoutes(rootDir, options = {}) {
948
974
  ignore: ["**/node_modules/**", "**/_*/**"]
949
975
  });
950
976
  const layoutMap = /* @__PURE__ */ new Map();
977
+ const loadingMap = /* @__PURE__ */ new Map();
978
+ const errorMap = /* @__PURE__ */ new Map();
951
979
  for (const file of files) {
952
980
  const type = getRouteType(file);
981
+ const { urlPath } = filePathToUrlPath(file, "");
953
982
  if (type === "layout") {
954
- const { urlPath } = filePathToUrlPath(file, "");
955
983
  const layoutPath = urlPath === "/" ? "/" : urlPath.replace(/\/layout$/, "") || "/";
956
984
  layoutMap.set(layoutPath, path2.join(appDir, file));
985
+ } else if (type === "loading") {
986
+ const loadingPath = urlPath === "/" ? "/" : urlPath.replace(/\/loading$/, "") || "/";
987
+ loadingMap.set(loadingPath, path2.join(appDir, file));
988
+ } else if (type === "error") {
989
+ const errorPath = urlPath === "/" ? "/" : urlPath.replace(/\/error$/, "") || "/";
990
+ errorMap.set(errorPath, path2.join(appDir, file));
957
991
  }
958
992
  }
959
993
  const routes = [];
@@ -971,7 +1005,9 @@ async function scanRoutes(rootDir, options = {}) {
971
1005
  params,
972
1006
  isCatchAll,
973
1007
  isOptionalCatchAll,
974
- layouts: type === "page" ? findLayouts(urlPath, layoutMap) : []
1008
+ layouts: type === "page" ? findLayouts(urlPath, layoutMap) : [],
1009
+ loading: type === "page" ? findLoading(urlPath, loadingMap) : void 0,
1010
+ error: type === "page" ? findError(urlPath, errorMap) : void 0
975
1011
  };
976
1012
  routes.push(route);
977
1013
  }
@@ -1029,23 +1065,222 @@ import { Writable } from "stream";
1029
1065
  // src/build/transform.ts
1030
1066
  init_esm_shims();
1031
1067
  import * as esbuild from "esbuild";
1068
+ import fs2 from "fs";
1069
+ import path4 from "path";
1070
+ import { pathToFileURL } from "url";
1071
+
1072
+ // src/build/persistent-cache.ts
1073
+ init_esm_shims();
1032
1074
  import fs from "fs";
1033
1075
  import path3 from "path";
1034
- import { pathToFileURL } from "url";
1076
+ import crypto from "crypto";
1077
+ var PersistentCache = class {
1078
+ cacheDir;
1079
+ manifestPath;
1080
+ manifest;
1081
+ constructor(rootDir = process.cwd()) {
1082
+ this.cacheDir = path3.join(rootDir, ".float", "cache");
1083
+ this.manifestPath = path3.join(this.cacheDir, "manifest.json");
1084
+ fs.mkdirSync(this.cacheDir, { recursive: true });
1085
+ this.manifest = this.loadManifest();
1086
+ }
1087
+ loadManifest() {
1088
+ if (fs.existsSync(this.manifestPath)) {
1089
+ try {
1090
+ const data = fs.readFileSync(this.manifestPath, "utf-8");
1091
+ return JSON.parse(data);
1092
+ } catch {
1093
+ }
1094
+ }
1095
+ return {
1096
+ version: "1.0",
1097
+ entries: {}
1098
+ };
1099
+ }
1100
+ saveManifest() {
1101
+ fs.writeFileSync(
1102
+ this.manifestPath,
1103
+ JSON.stringify(this.manifest, null, 2)
1104
+ );
1105
+ }
1106
+ /**
1107
+ * Generate hash for content
1108
+ */
1109
+ hash(content) {
1110
+ return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
1111
+ }
1112
+ /**
1113
+ * Get cache key path
1114
+ */
1115
+ getKeyPath(key) {
1116
+ const safeKey = key.replace(/[^a-z0-9_-]/gi, "_");
1117
+ return path3.join(this.cacheDir, `${safeKey}.cache`);
1118
+ }
1119
+ /**
1120
+ * Check if cache entry is valid
1121
+ */
1122
+ has(key, contentHash) {
1123
+ const entry = this.manifest.entries[key];
1124
+ if (!entry) return false;
1125
+ const cachePath = this.getKeyPath(key);
1126
+ if (!fs.existsSync(cachePath)) {
1127
+ delete this.manifest.entries[key];
1128
+ this.saveManifest();
1129
+ return false;
1130
+ }
1131
+ if (contentHash && entry.hash !== contentHash) {
1132
+ return false;
1133
+ }
1134
+ return true;
1135
+ }
1136
+ /**
1137
+ * Get cached value
1138
+ */
1139
+ get(key) {
1140
+ if (!this.has(key)) return null;
1141
+ try {
1142
+ const cachePath = this.getKeyPath(key);
1143
+ const data = fs.readFileSync(cachePath, "utf-8");
1144
+ const entry = JSON.parse(data);
1145
+ return entry.value;
1146
+ } catch {
1147
+ return null;
1148
+ }
1149
+ }
1150
+ /**
1151
+ * Set cache value
1152
+ */
1153
+ set(key, value, content) {
1154
+ const entry = {
1155
+ key,
1156
+ value,
1157
+ timestamp: Date.now(),
1158
+ hash: content ? this.hash(content) : this.hash(JSON.stringify(value))
1159
+ };
1160
+ const cachePath = this.getKeyPath(key);
1161
+ const data = JSON.stringify(entry);
1162
+ fs.writeFileSync(cachePath, data);
1163
+ this.manifest.entries[key] = {
1164
+ hash: entry.hash,
1165
+ timestamp: entry.timestamp,
1166
+ size: Buffer.byteLength(data)
1167
+ };
1168
+ this.saveManifest();
1169
+ }
1170
+ /**
1171
+ * Delete cache entry
1172
+ */
1173
+ delete(key) {
1174
+ const cachePath = this.getKeyPath(key);
1175
+ if (fs.existsSync(cachePath)) {
1176
+ fs.unlinkSync(cachePath);
1177
+ }
1178
+ if (this.manifest.entries[key]) {
1179
+ delete this.manifest.entries[key];
1180
+ this.saveManifest();
1181
+ return true;
1182
+ }
1183
+ return false;
1184
+ }
1185
+ /**
1186
+ * Clear all cache
1187
+ */
1188
+ clear() {
1189
+ if (fs.existsSync(this.cacheDir)) {
1190
+ fs.rmSync(this.cacheDir, { recursive: true });
1191
+ fs.mkdirSync(this.cacheDir, { recursive: true });
1192
+ }
1193
+ this.manifest = {
1194
+ version: "1.0",
1195
+ entries: {}
1196
+ };
1197
+ this.saveManifest();
1198
+ }
1199
+ /**
1200
+ * Get cache statistics
1201
+ */
1202
+ stats() {
1203
+ const entries = Object.values(this.manifest.entries);
1204
+ const size = entries.reduce((acc, e) => acc + e.size, 0);
1205
+ const timestamps = entries.map((e) => e.timestamp);
1206
+ return {
1207
+ entries: entries.length,
1208
+ size,
1209
+ oldestEntry: timestamps.length > 0 ? Math.min(...timestamps) : null,
1210
+ newestEntry: timestamps.length > 0 ? Math.max(...timestamps) : null
1211
+ };
1212
+ }
1213
+ /**
1214
+ * Clean old entries (older than maxAge milliseconds)
1215
+ */
1216
+ prune(maxAge = 7 * 24 * 60 * 60 * 1e3) {
1217
+ const now = Date.now();
1218
+ let cleaned = 0;
1219
+ for (const [key, entry] of Object.entries(this.manifest.entries)) {
1220
+ if (now - entry.timestamp > maxAge) {
1221
+ this.delete(key);
1222
+ cleaned++;
1223
+ }
1224
+ }
1225
+ return cleaned;
1226
+ }
1227
+ };
1228
+ var globalCache = null;
1229
+ function getCache(rootDir) {
1230
+ if (!globalCache) {
1231
+ globalCache = new PersistentCache(rootDir);
1232
+ }
1233
+ return globalCache;
1234
+ }
1235
+
1236
+ // src/build/transform.ts
1035
1237
  var moduleCache = /* @__PURE__ */ new Map();
1036
- async function transformFile(filePath) {
1037
- const absolutePath = path3.isAbsolute(filePath) ? filePath : path3.resolve(filePath);
1038
- if (!fs.existsSync(absolutePath)) {
1238
+ async function transformFile(filePath, useCache = true) {
1239
+ const absolutePath = path4.isAbsolute(filePath) ? filePath : path4.resolve(filePath);
1240
+ if (!fs2.existsSync(absolutePath)) {
1039
1241
  throw new Error(`File not found: ${absolutePath}`);
1040
1242
  }
1041
- const stats = fs.statSync(absolutePath);
1243
+ const stats = fs2.statSync(absolutePath);
1042
1244
  const mtime = stats.mtimeMs;
1043
1245
  const cached = moduleCache.get(absolutePath);
1044
1246
  if (cached && cached.mtime === mtime) {
1045
1247
  return cached.module;
1046
1248
  }
1047
- const source = fs.readFileSync(absolutePath, "utf-8");
1048
- const ext = path3.extname(absolutePath);
1249
+ if (useCache) {
1250
+ const cache = getCache();
1251
+ const source2 = fs2.readFileSync(absolutePath, "utf-8");
1252
+ const sourceHash = __require("crypto").createHash("sha256").update(source2).digest("hex").slice(0, 16);
1253
+ const cacheKey = `transform_${absolutePath}_${sourceHash}`;
1254
+ if (cache.has(cacheKey)) {
1255
+ const cachedCode = cache.get(cacheKey);
1256
+ if (cachedCode) {
1257
+ const tempDir2 = path4.join(process.cwd(), ".float", ".cache");
1258
+ fs2.mkdirSync(tempDir2, { recursive: true });
1259
+ const tempFile2 = path4.join(tempDir2, `${path4.basename(absolutePath, path4.extname(absolutePath))}_${Date.now()}.mjs`);
1260
+ fs2.writeFileSync(tempFile2, cachedCode);
1261
+ try {
1262
+ const module = await import(pathToFileURL(tempFile2).href);
1263
+ moduleCache.set(absolutePath, { module, mtime });
1264
+ setImmediate(() => {
1265
+ try {
1266
+ fs2.unlinkSync(tempFile2);
1267
+ } catch {
1268
+ }
1269
+ });
1270
+ return module;
1271
+ } catch (error) {
1272
+ setImmediate(() => {
1273
+ try {
1274
+ fs2.unlinkSync(tempFile2);
1275
+ } catch {
1276
+ }
1277
+ });
1278
+ }
1279
+ }
1280
+ }
1281
+ }
1282
+ const source = fs2.readFileSync(absolutePath, "utf-8");
1283
+ const ext = path4.extname(absolutePath);
1049
1284
  const loader = getLoader(ext);
1050
1285
  const result = await esbuild.transform(source, {
1051
1286
  loader,
@@ -1055,25 +1290,31 @@ async function transformFile(filePath) {
1055
1290
  sourcemap: "inline",
1056
1291
  sourcefile: absolutePath
1057
1292
  });
1058
- const tempDir = path3.join(process.cwd(), ".float", ".cache");
1059
- fs.mkdirSync(tempDir, { recursive: true });
1060
- const tempFile = path3.join(tempDir, `${path3.basename(absolutePath, ext)}_${Date.now()}.mjs`);
1293
+ const tempDir = path4.join(process.cwd(), ".float", ".cache");
1294
+ fs2.mkdirSync(tempDir, { recursive: true });
1295
+ const tempFile = path4.join(tempDir, `${path4.basename(absolutePath, ext)}_${Date.now()}.mjs`);
1061
1296
  let code = result.code;
1062
- code = rewriteImports(code, path3.dirname(absolutePath));
1063
- fs.writeFileSync(tempFile, code);
1297
+ code = rewriteImports(code, path4.dirname(absolutePath));
1298
+ fs2.writeFileSync(tempFile, code);
1064
1299
  try {
1065
1300
  const module = await import(pathToFileURL(tempFile).href);
1066
1301
  moduleCache.set(absolutePath, { module, mtime });
1302
+ if (useCache) {
1303
+ const cache = getCache();
1304
+ const sourceHash = __require("crypto").createHash("sha256").update(source).digest("hex").slice(0, 16);
1305
+ const cacheKey = `transform_${absolutePath}_${sourceHash}`;
1306
+ cache.set(cacheKey, code, source);
1307
+ }
1067
1308
  setImmediate(() => {
1068
1309
  try {
1069
- fs.unlinkSync(tempFile);
1310
+ fs2.unlinkSync(tempFile);
1070
1311
  } catch {
1071
1312
  }
1072
1313
  });
1073
1314
  return module;
1074
1315
  } catch (error) {
1075
1316
  try {
1076
- fs.unlinkSync(tempFile);
1317
+ fs2.unlinkSync(tempFile);
1077
1318
  } catch {
1078
1319
  }
1079
1320
  throw error;
@@ -1102,18 +1343,18 @@ function getLoader(ext) {
1102
1343
  function rewriteImports(code, baseDir) {
1103
1344
  const importRegex = /from\s+['"](\.[^'"]+)['"]/g;
1104
1345
  return code.replace(importRegex, (match, importPath) => {
1105
- let resolvedPath = path3.resolve(baseDir, importPath);
1346
+ let resolvedPath = path4.resolve(baseDir, importPath);
1106
1347
  const extensions = [".tsx", ".ts", ".jsx", ".js", ".mjs", ""];
1107
1348
  let found = false;
1108
1349
  for (const ext of extensions) {
1109
1350
  const tryPath = resolvedPath + ext;
1110
- if (fs.existsSync(tryPath)) {
1351
+ if (fs2.existsSync(tryPath)) {
1111
1352
  resolvedPath = tryPath;
1112
1353
  found = true;
1113
1354
  break;
1114
1355
  }
1115
- const indexPath = path3.join(resolvedPath, `index${ext}`);
1116
- if (fs.existsSync(indexPath)) {
1356
+ const indexPath = path4.join(resolvedPath, `index${ext}`);
1357
+ if (fs2.existsSync(indexPath)) {
1117
1358
  resolvedPath = indexPath;
1118
1359
  found = true;
1119
1360
  break;
@@ -2464,11 +2705,214 @@ function generateExamplesPage() {
2464
2705
  ` + footer;
2465
2706
  }
2466
2707
 
2708
+ // src/build/css-processor.ts
2709
+ init_esm_shims();
2710
+ import fs4 from "fs";
2711
+ import path6 from "path";
2712
+
2713
+ // src/build/tailwind-setup.ts
2714
+ init_esm_shims();
2715
+ import fs3 from "fs";
2716
+ import path5 from "path";
2717
+ import pc from "picocolors";
2718
+ function checkTailwindSetup(rootDir) {
2719
+ const possibleConfigs = [
2720
+ "tailwind.config.js",
2721
+ "tailwind.config.ts",
2722
+ "tailwind.config.mjs",
2723
+ "tailwind.config.cjs"
2724
+ ];
2725
+ let configPath = null;
2726
+ for (const config of possibleConfigs) {
2727
+ const fullPath = path5.join(rootDir, config);
2728
+ if (fs3.existsSync(fullPath)) {
2729
+ configPath = fullPath;
2730
+ break;
2731
+ }
2732
+ }
2733
+ const globalsPath = path5.join(rootDir, "app", "globals.css");
2734
+ const hasGlobals = fs3.existsSync(globalsPath);
2735
+ return {
2736
+ hasTailwind: !!configPath,
2737
+ configPath,
2738
+ globalsPath: hasGlobals ? globalsPath : null,
2739
+ needsSetup: !configPath || !hasGlobals
2740
+ };
2741
+ }
2742
+ async function setupTailwind(rootDir, options = {}) {
2743
+ const { force = false, silent = false } = options;
2744
+ const config = checkTailwindSetup(rootDir);
2745
+ if (!force && !config.needsSetup) {
2746
+ return;
2747
+ }
2748
+ if (!silent) {
2749
+ console.log(pc.cyan("\n\u{1F3A8} Setting up Tailwind CSS..."));
2750
+ }
2751
+ if (!config.configPath || force) {
2752
+ const tailwindConfig = `/** @type {import('tailwindcss').Config} */
2753
+ export default {
2754
+ content: [
2755
+ './app/**/*.{js,ts,jsx,tsx}',
2756
+ './components/**/*.{js,ts,jsx,tsx}',
2757
+ ],
2758
+ theme: {
2759
+ extend: {},
2760
+ },
2761
+ plugins: [],
2762
+ }
2763
+ `;
2764
+ const configPath = path5.join(rootDir, "tailwind.config.js");
2765
+ fs3.writeFileSync(configPath, tailwindConfig);
2766
+ if (!silent) {
2767
+ console.log(pc.green(" \u2713 Created tailwind.config.js"));
2768
+ }
2769
+ }
2770
+ const postcssPath = path5.join(rootDir, "postcss.config.js");
2771
+ if (!fs3.existsSync(postcssPath) || force) {
2772
+ const postcssConfig = `export default {
2773
+ plugins: {
2774
+ tailwindcss: {},
2775
+ autoprefixer: {},
2776
+ },
2777
+ }
2778
+ `;
2779
+ fs3.writeFileSync(postcssPath, postcssConfig);
2780
+ if (!silent) {
2781
+ console.log(pc.green(" \u2713 Created postcss.config.js"));
2782
+ }
2783
+ }
2784
+ const appDir = path5.join(rootDir, "app");
2785
+ if (!fs3.existsSync(appDir)) {
2786
+ fs3.mkdirSync(appDir, { recursive: true });
2787
+ }
2788
+ const globalsPath = path5.join(appDir, "globals.css");
2789
+ if (!fs3.existsSync(globalsPath) || force) {
2790
+ const globalsCss = `@tailwind base;
2791
+ @tailwind components;
2792
+ @tailwind utilities;
2793
+ `;
2794
+ fs3.writeFileSync(globalsPath, globalsCss);
2795
+ if (!silent) {
2796
+ console.log(pc.green(" \u2713 Created app/globals.css"));
2797
+ }
2798
+ }
2799
+ const layoutPath = path5.join(appDir, "layout.tsx");
2800
+ if (!fs3.existsSync(layoutPath)) {
2801
+ const layoutContent = `import './globals.css'
2802
+
2803
+ export default function RootLayout({
2804
+ children,
2805
+ }: {
2806
+ children: React.ReactNode
2807
+ }) {
2808
+ return (
2809
+ <html lang="en">
2810
+ <body>{children}</body>
2811
+ </html>
2812
+ )
2813
+ }
2814
+ `;
2815
+ fs3.writeFileSync(layoutPath, layoutContent);
2816
+ if (!silent) {
2817
+ console.log(pc.green(" \u2713 Created app/layout.tsx"));
2818
+ }
2819
+ }
2820
+ if (!silent) {
2821
+ console.log(pc.green("\n\u2728 Tailwind CSS ready!\n"));
2822
+ }
2823
+ }
2824
+ function checkTailwindDeps(rootDir) {
2825
+ const packageJsonPath = path5.join(rootDir, "package.json");
2826
+ if (!fs3.existsSync(packageJsonPath)) {
2827
+ return {
2828
+ hasPackageJson: false,
2829
+ hasTailwind: false,
2830
+ hasPostCSS: false,
2831
+ hasAutoprefixer: false
2832
+ };
2833
+ }
2834
+ const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf-8"));
2835
+ const allDeps = {
2836
+ ...packageJson.dependencies,
2837
+ ...packageJson.devDependencies
2838
+ };
2839
+ return {
2840
+ hasPackageJson: true,
2841
+ hasTailwind: !!allDeps["tailwindcss"],
2842
+ hasPostCSS: !!allDeps["postcss"],
2843
+ hasAutoprefixer: !!allDeps["autoprefixer"]
2844
+ };
2845
+ }
2846
+ function getTailwindInstallCommand(rootDir) {
2847
+ const deps = checkTailwindDeps(rootDir);
2848
+ if (!deps.hasPackageJson) {
2849
+ return null;
2850
+ }
2851
+ const missing = [];
2852
+ if (!deps.hasTailwind) missing.push("tailwindcss");
2853
+ if (!deps.hasPostCSS) missing.push("postcss");
2854
+ if (!deps.hasAutoprefixer) missing.push("autoprefixer");
2855
+ if (missing.length === 0) {
2856
+ return null;
2857
+ }
2858
+ const hasYarnLock = fs3.existsSync(path5.join(rootDir, "yarn.lock"));
2859
+ const hasPnpmLock = fs3.existsSync(path5.join(rootDir, "pnpm-lock.yaml"));
2860
+ const hasBunLock = fs3.existsSync(path5.join(rootDir, "bun.lockb"));
2861
+ let pm = "npm install -D";
2862
+ if (hasBunLock) pm = "bun add -d";
2863
+ else if (hasPnpmLock) pm = "pnpm add -D";
2864
+ else if (hasYarnLock) pm = "yarn add -D";
2865
+ return `${pm} ${missing.join(" ")}`;
2866
+ }
2867
+
2868
+ // src/build/css-processor.ts
2869
+ async function processCSS(filePath, rootDir = process.cwd()) {
2870
+ const content = fs4.readFileSync(filePath, "utf-8");
2871
+ const tailwindConfig = checkTailwindSetup(rootDir);
2872
+ if (!tailwindConfig.hasTailwind) {
2873
+ return { code: content };
2874
+ }
2875
+ try {
2876
+ const postcss = await import("postcss").then((m) => m.default);
2877
+ const tailwindcss = await import("tailwindcss").then((m) => m.default);
2878
+ const autoprefixer = await import("autoprefixer").then((m) => m.default);
2879
+ const configPath = tailwindConfig.configPath || path6.join(rootDir, "tailwind.config.js");
2880
+ let tailwindConfigModule = {};
2881
+ if (fs4.existsSync(configPath)) {
2882
+ const configUrl = new URL(`file://${configPath}`);
2883
+ tailwindConfigModule = await import(configUrl.href).then((m) => m.default || m);
2884
+ }
2885
+ const result = await postcss([
2886
+ tailwindcss(tailwindConfigModule),
2887
+ autoprefixer()
2888
+ ]).process(content, {
2889
+ from: filePath,
2890
+ to: filePath,
2891
+ map: { inline: false }
2892
+ });
2893
+ return {
2894
+ code: result.css,
2895
+ map: result.map?.toString()
2896
+ };
2897
+ } catch (error) {
2898
+ console.warn("CSS processing failed, serving raw CSS:", error);
2899
+ return { code: content };
2900
+ }
2901
+ }
2902
+ function needsCSSProcessing(filePath, rootDir) {
2903
+ const config = checkTailwindSetup(rootDir);
2904
+ if (!config.hasTailwind) {
2905
+ return false;
2906
+ }
2907
+ const content = fs4.readFileSync(filePath, "utf-8");
2908
+ return content.includes("@tailwind") || content.includes("@apply");
2909
+ }
2910
+
2467
2911
  // src/server/dev-server.ts
2468
2912
  async function createDevServer(options) {
2469
2913
  const { port, host, open } = options;
2470
2914
  const rootDir = process.cwd();
2471
- const publicDir = path4.join(rootDir, "public");
2915
+ const publicDir = path7.join(rootDir, "public");
2472
2916
  let routes = [];
2473
2917
  let server = null;
2474
2918
  let wss = null;
@@ -2476,9 +2920,20 @@ async function createDevServer(options) {
2476
2920
  async function refreshRoutes() {
2477
2921
  try {
2478
2922
  routes = await scanRoutes(rootDir);
2479
- console.log(pc.dim(` \u{1F4C1} Found ${routes.length} routes`));
2923
+ console.log(pc2.dim(` \u{1F4C1} Found ${routes.length} routes`));
2924
+ const tailwindConfig = checkTailwindSetup(rootDir);
2925
+ if (tailwindConfig.needsSetup) {
2926
+ console.log(pc2.yellow(" \u26A0\uFE0F Tailwind not configured"));
2927
+ const installCmd = getTailwindInstallCommand(rootDir);
2928
+ if (installCmd) {
2929
+ console.log(pc2.dim(` \u{1F4A1} Run: ${installCmd}`));
2930
+ console.log(pc2.dim(` \u{1F4A1} Then: npx float dev`));
2931
+ } else {
2932
+ await setupTailwind(rootDir);
2933
+ }
2934
+ }
2480
2935
  } catch (error) {
2481
- console.error(pc.red("Failed to scan routes:"), error);
2936
+ console.error(pc2.red("Failed to scan routes:"), error);
2482
2937
  }
2483
2938
  }
2484
2939
  function notifyClients(type, data) {
@@ -2539,16 +2994,46 @@ ${FLOAT_ERROR_OVERLAY}
2539
2994
  async function handleRequest(req, res) {
2540
2995
  const url = new URL(req.url || "/", `http://${host}:${port}`);
2541
2996
  const pathname = url.pathname;
2542
- console.log(pc.dim(` ${req.method} ${pathname}`));
2997
+ console.log(pc2.dim(` ${req.method} ${pathname}`));
2543
2998
  try {
2544
- const publicFilePath = path4.join(publicDir, pathname);
2545
- if (fs2.existsSync(publicFilePath) && fs2.statSync(publicFilePath).isFile()) {
2546
- const content = fs2.readFileSync(publicFilePath);
2999
+ const publicFilePath = path7.join(publicDir, pathname);
3000
+ if (fs5.existsSync(publicFilePath) && fs5.statSync(publicFilePath).isFile()) {
3001
+ const content = fs5.readFileSync(publicFilePath);
2547
3002
  const contentType = mime.lookup(publicFilePath) || "application/octet-stream";
2548
3003
  res.writeHead(200, { "Content-Type": contentType });
2549
3004
  res.end(content);
2550
3005
  return;
2551
3006
  }
3007
+ if (pathname.endsWith(".css")) {
3008
+ const cssPath = path7.join(rootDir, "app", pathname.replace(/^\//, ""));
3009
+ if (fs5.existsSync(cssPath)) {
3010
+ try {
3011
+ const needsProcessing = needsCSSProcessing(cssPath, rootDir);
3012
+ if (needsProcessing) {
3013
+ const result = await processCSS(cssPath, rootDir);
3014
+ res.writeHead(200, {
3015
+ "Content-Type": "text/css",
3016
+ "Cache-Control": "no-cache"
3017
+ });
3018
+ res.end(result.code);
3019
+ } else {
3020
+ const content = fs5.readFileSync(cssPath, "utf-8");
3021
+ res.writeHead(200, {
3022
+ "Content-Type": "text/css",
3023
+ "Cache-Control": "no-cache"
3024
+ });
3025
+ res.end(content);
3026
+ }
3027
+ return;
3028
+ } catch (error) {
3029
+ console.error(pc2.red("CSS processing error:"), error);
3030
+ const content = fs5.readFileSync(cssPath, "utf-8");
3031
+ res.writeHead(200, { "Content-Type": "text/css" });
3032
+ res.end(content);
3033
+ return;
3034
+ }
3035
+ }
3036
+ }
2552
3037
  if (pathname.startsWith("/_float/")) {
2553
3038
  res.writeHead(200, { "Content-Type": "application/javascript" });
2554
3039
  res.end("// Float.js internal asset");
@@ -2613,7 +3098,7 @@ ${FLOAT_ERROR_OVERLAY}
2613
3098
  });
2614
3099
  res.end(html);
2615
3100
  } catch (error) {
2616
- console.error(pc.red("Request error:"), error);
3101
+ console.error(pc2.red("Request error:"), error);
2617
3102
  res.writeHead(500, { "Content-Type": "text/html" });
2618
3103
  res.end(createErrorPage(error));
2619
3104
  }
@@ -2642,7 +3127,7 @@ ${FLOAT_ERROR_OVERLAY}
2642
3127
  const responseBody = await response.text();
2643
3128
  res.end(responseBody);
2644
3129
  } catch (error) {
2645
- console.error(pc.red("API route error:"), error);
3130
+ console.error(pc2.red("API route error:"), error);
2646
3131
  res.writeHead(500, { "Content-Type": "application/json" });
2647
3132
  res.end(JSON.stringify({ error: "Internal server error" }));
2648
3133
  }
@@ -2657,9 +3142,9 @@ ${FLOAT_ERROR_OVERLAY}
2657
3142
  });
2658
3143
  const watcher = chokidar.watch(
2659
3144
  [
2660
- path4.join(rootDir, "app/**/*.{ts,tsx,js,jsx}"),
2661
- path4.join(rootDir, "components/**/*.{ts,tsx,js,jsx}"),
2662
- path4.join(rootDir, "lib/**/*.{ts,tsx,js,jsx}")
3145
+ path7.join(rootDir, "app/**/*.{ts,tsx,js,jsx}"),
3146
+ path7.join(rootDir, "components/**/*.{ts,tsx,js,jsx}"),
3147
+ path7.join(rootDir, "lib/**/*.{ts,tsx,js,jsx}")
2663
3148
  ],
2664
3149
  {
2665
3150
  ignored: /node_modules/,
@@ -2667,8 +3152,8 @@ ${FLOAT_ERROR_OVERLAY}
2667
3152
  }
2668
3153
  );
2669
3154
  watcher.on("change", async (filePath) => {
2670
- console.log(pc.yellow(`
2671
- \u26A1 File changed: ${path4.relative(rootDir, filePath)}`));
3155
+ console.log(pc2.yellow(`
3156
+ \u26A1 File changed: ${path7.relative(rootDir, filePath)}`));
2672
3157
  if (filePath.includes("/app/")) {
2673
3158
  await refreshRoutes();
2674
3159
  }
@@ -2676,31 +3161,31 @@ ${FLOAT_ERROR_OVERLAY}
2676
3161
  });
2677
3162
  watcher.on("add", async (filePath) => {
2678
3163
  if (filePath.includes("/app/")) {
2679
- console.log(pc.green(`
2680
- \u2795 File added: ${path4.relative(rootDir, filePath)}`));
3164
+ console.log(pc2.green(`
3165
+ \u2795 File added: ${path7.relative(rootDir, filePath)}`));
2681
3166
  await refreshRoutes();
2682
3167
  notifyClients("reload");
2683
3168
  }
2684
3169
  });
2685
3170
  watcher.on("unlink", async (filePath) => {
2686
3171
  if (filePath.includes("/app/")) {
2687
- console.log(pc.red(`
2688
- \u2796 File removed: ${path4.relative(rootDir, filePath)}`));
3172
+ console.log(pc2.red(`
3173
+ \u2796 File removed: ${path7.relative(rootDir, filePath)}`));
2689
3174
  await refreshRoutes();
2690
3175
  notifyClients("reload");
2691
3176
  }
2692
3177
  });
2693
3178
  return new Promise((resolve, reject) => {
2694
3179
  server.listen(port, host, () => {
2695
- console.log(pc.green(` \u2705 Server running at ${pc.cyan(`http://${host}:${port}`)}`));
2696
- console.log(pc.dim(` \u26A1 HMR enabled on ws://${host}:${port + 1}
3180
+ console.log(pc2.green(` \u2705 Server running at ${pc2.cyan(`http://${host}:${port}`)}`));
3181
+ console.log(pc2.dim(` \u26A1 HMR enabled on ws://${host}:${port + 1}
2697
3182
  `));
2698
- console.log(pc.bold(" Routes:"));
3183
+ console.log(pc2.bold(" Routes:"));
2699
3184
  routes.forEach((route) => {
2700
3185
  if (route.type === "page") {
2701
- console.log(pc.dim(` ${pc.green("\u25CF")} ${route.path}`));
3186
+ console.log(pc2.dim(` ${pc2.green("\u25CF")} ${route.path}`));
2702
3187
  } else if (route.type === "api") {
2703
- console.log(pc.dim(` ${pc.blue("\u25C6")} ${route.path} (API)`));
3188
+ console.log(pc2.dim(` ${pc2.blue("\u25C6")} ${route.path} (API)`));
2704
3189
  }
2705
3190
  });
2706
3191
  console.log("");
@@ -2820,9 +3305,9 @@ function escapeHtml2(text) {
2820
3305
  // src/build/index.ts
2821
3306
  init_esm_shims();
2822
3307
  import * as esbuild2 from "esbuild";
2823
- import fs3 from "fs";
2824
- import path5 from "path";
2825
- import pc2 from "picocolors";
3308
+ import fs6 from "fs";
3309
+ import path8 from "path";
3310
+ import pc3 from "picocolors";
2826
3311
  var DEFAULT_BUILD_OPTIONS = {
2827
3312
  analyze: false,
2828
3313
  minify: true,
@@ -2832,27 +3317,27 @@ async function build2(options = {}) {
2832
3317
  const opts = { ...DEFAULT_BUILD_OPTIONS, ...options };
2833
3318
  const startTime = Date.now();
2834
3319
  const rootDir = process.cwd();
2835
- const outputDir = path5.join(rootDir, ".float");
2836
- if (fs3.existsSync(outputDir)) {
2837
- fs3.rmSync(outputDir, { recursive: true });
2838
- }
2839
- fs3.mkdirSync(outputDir, { recursive: true });
2840
- fs3.mkdirSync(path5.join(outputDir, "pages"), { recursive: true });
2841
- fs3.mkdirSync(path5.join(outputDir, "static"), { recursive: true });
2842
- fs3.mkdirSync(path5.join(outputDir, "server"), { recursive: true });
2843
- console.log(pc2.dim(" Scanning routes..."));
3320
+ const outputDir = path8.join(rootDir, ".float");
3321
+ if (fs6.existsSync(outputDir)) {
3322
+ fs6.rmSync(outputDir, { recursive: true });
3323
+ }
3324
+ fs6.mkdirSync(outputDir, { recursive: true });
3325
+ fs6.mkdirSync(path8.join(outputDir, "pages"), { recursive: true });
3326
+ fs6.mkdirSync(path8.join(outputDir, "static"), { recursive: true });
3327
+ fs6.mkdirSync(path8.join(outputDir, "server"), { recursive: true });
3328
+ console.log(pc3.dim(" Scanning routes..."));
2844
3329
  const routes = await scanRoutes(rootDir);
2845
3330
  const pageRoutes = routes.filter((r) => r.type === "page" && !r.params.length);
2846
3331
  const dynamicRoutes = routes.filter((r) => r.type === "page" && r.params.length > 0);
2847
3332
  const apiRoutes = routes.filter((r) => r.type === "api");
2848
- console.log(pc2.dim(` Found ${pageRoutes.length} static pages, ${dynamicRoutes.length} dynamic routes, ${apiRoutes.length} API routes`));
2849
- console.log(pc2.dim(" Building client bundle..."));
3333
+ console.log(pc3.dim(` Found ${pageRoutes.length} static pages, ${dynamicRoutes.length} dynamic routes, ${apiRoutes.length} API routes`));
3334
+ console.log(pc3.dim(" Building client bundle..."));
2850
3335
  const clientEntryPoints = routes.filter((r) => r.type === "page").map((r) => r.absolutePath);
2851
3336
  if (clientEntryPoints.length > 0) {
2852
3337
  await esbuild2.build({
2853
3338
  entryPoints: clientEntryPoints,
2854
3339
  bundle: true,
2855
- outdir: path5.join(outputDir, "static", "_float"),
3340
+ outdir: path8.join(outputDir, "static", "_float"),
2856
3341
  format: "esm",
2857
3342
  splitting: true,
2858
3343
  minify: opts.minify,
@@ -2874,13 +3359,13 @@ async function build2(options = {}) {
2874
3359
  metafile: opts.analyze
2875
3360
  });
2876
3361
  }
2877
- console.log(pc2.dim(" Building server bundle..."));
3362
+ console.log(pc3.dim(" Building server bundle..."));
2878
3363
  const serverEntryPoints = routes.map((r) => r.absolutePath);
2879
3364
  if (serverEntryPoints.length > 0) {
2880
3365
  await esbuild2.build({
2881
3366
  entryPoints: serverEntryPoints,
2882
3367
  bundle: true,
2883
- outdir: path5.join(outputDir, "server"),
3368
+ outdir: path8.join(outputDir, "server"),
2884
3369
  format: "esm",
2885
3370
  platform: "node",
2886
3371
  target: ["node18"],
@@ -2897,26 +3382,26 @@ async function build2(options = {}) {
2897
3382
  external: ["react", "react-dom", "@float/core"]
2898
3383
  });
2899
3384
  }
2900
- console.log(pc2.dim(" Pre-rendering static pages..."));
3385
+ console.log(pc3.dim(" Pre-rendering static pages..."));
2901
3386
  const prerenderedPages = [];
2902
3387
  for (const route of pageRoutes) {
2903
3388
  try {
2904
3389
  const html = await renderPage(route, {}, { isDev: false });
2905
- const outputPath = route.path === "/" ? path5.join(outputDir, "pages", "index.html") : path5.join(outputDir, "pages", route.path, "index.html");
2906
- fs3.mkdirSync(path5.dirname(outputPath), { recursive: true });
2907
- fs3.writeFileSync(outputPath, html);
3390
+ const outputPath = route.path === "/" ? path8.join(outputDir, "pages", "index.html") : path8.join(outputDir, "pages", route.path, "index.html");
3391
+ fs6.mkdirSync(path8.dirname(outputPath), { recursive: true });
3392
+ fs6.writeFileSync(outputPath, html);
2908
3393
  prerenderedPages.push(route.path);
2909
- console.log(pc2.dim(` \u2713 ${route.path}`));
3394
+ console.log(pc3.dim(` \u2713 ${route.path}`));
2910
3395
  } catch (error) {
2911
- console.log(pc2.yellow(` \u26A0 ${route.path} (will render at runtime)`));
3396
+ console.log(pc3.yellow(` \u26A0 ${route.path} (will render at runtime)`));
2912
3397
  }
2913
3398
  }
2914
- console.log(pc2.dim(" Building API routes..."));
3399
+ console.log(pc3.dim(" Building API routes..."));
2915
3400
  for (const route of apiRoutes) {
2916
3401
  await esbuild2.build({
2917
3402
  entryPoints: [route.absolutePath],
2918
3403
  bundle: true,
2919
- outfile: path5.join(outputDir, "server", "api", `${route.path.replace(/\//g, "_")}.js`),
3404
+ outfile: path8.join(outputDir, "server", "api", `${route.path.replace(/\//g, "_")}.js`),
2920
3405
  format: "esm",
2921
3406
  platform: "neutral",
2922
3407
  // Edge compatible
@@ -2924,10 +3409,10 @@ async function build2(options = {}) {
2924
3409
  minify: true
2925
3410
  });
2926
3411
  }
2927
- const publicDir = path5.join(rootDir, "public");
2928
- if (fs3.existsSync(publicDir)) {
2929
- console.log(pc2.dim(" Copying public assets..."));
2930
- copyDir(publicDir, path5.join(outputDir, "static"));
3412
+ const publicDir = path8.join(rootDir, "public");
3413
+ if (fs6.existsSync(publicDir)) {
3414
+ console.log(pc3.dim(" Copying public assets..."));
3415
+ copyDir(publicDir, path8.join(outputDir, "static"));
2931
3416
  }
2932
3417
  const manifest = {
2933
3418
  version: 1,
@@ -2936,19 +3421,19 @@ async function build2(options = {}) {
2936
3421
  path: r.path,
2937
3422
  type: r.type,
2938
3423
  filePath: r.filePath,
2939
- absolutePath: path5.relative(rootDir, r.absolutePath),
3424
+ absolutePath: path8.relative(rootDir, r.absolutePath),
2940
3425
  params: r.params,
2941
3426
  isCatchAll: r.isCatchAll,
2942
3427
  isOptionalCatchAll: r.isOptionalCatchAll,
2943
- layouts: r.layouts.map((l) => path5.relative(rootDir, l)),
3428
+ layouts: r.layouts.map((l) => path8.relative(rootDir, l)),
2944
3429
  prerendered: prerenderedPages.includes(r.path)
2945
3430
  })),
2946
3431
  staticPages: prerenderedPages,
2947
3432
  dynamicRoutes: dynamicRoutes.map((r) => r.path),
2948
3433
  apiRoutes: apiRoutes.map((r) => r.path)
2949
3434
  };
2950
- fs3.writeFileSync(
2951
- path5.join(outputDir, "routes-manifest.json"),
3435
+ fs6.writeFileSync(
3436
+ path8.join(outputDir, "routes-manifest.json"),
2952
3437
  JSON.stringify(manifest, null, 2)
2953
3438
  );
2954
3439
  const duration = Date.now() - startTime;
@@ -2958,16 +3443,16 @@ async function build2(options = {}) {
2958
3443
  routes: routes.length,
2959
3444
  pages: prerenderedPages.length
2960
3445
  };
2961
- fs3.writeFileSync(
2962
- path5.join(outputDir, "build-info.json"),
3446
+ fs6.writeFileSync(
3447
+ path8.join(outputDir, "build-info.json"),
2963
3448
  JSON.stringify(buildInfo, null, 2)
2964
3449
  );
2965
3450
  console.log("");
2966
- console.log(pc2.bold(" Build Summary:"));
2967
- console.log(pc2.dim(` Static Pages: ${prerenderedPages.length}`));
2968
- console.log(pc2.dim(` Dynamic Routes: ${dynamicRoutes.length}`));
2969
- console.log(pc2.dim(` API Routes: ${apiRoutes.length}`));
2970
- console.log(pc2.dim(` Output: .float/`));
3451
+ console.log(pc3.bold(" Build Summary:"));
3452
+ console.log(pc3.dim(` Static Pages: ${prerenderedPages.length}`));
3453
+ console.log(pc3.dim(` Dynamic Routes: ${dynamicRoutes.length}`));
3454
+ console.log(pc3.dim(` API Routes: ${apiRoutes.length}`));
3455
+ console.log(pc3.dim(` Output: .float/`));
2971
3456
  return {
2972
3457
  routes,
2973
3458
  duration,
@@ -2977,15 +3462,15 @@ async function build2(options = {}) {
2977
3462
  };
2978
3463
  }
2979
3464
  function copyDir(src, dest) {
2980
- fs3.mkdirSync(dest, { recursive: true });
2981
- const entries = fs3.readdirSync(src, { withFileTypes: true });
3465
+ fs6.mkdirSync(dest, { recursive: true });
3466
+ const entries = fs6.readdirSync(src, { withFileTypes: true });
2982
3467
  for (const entry of entries) {
2983
- const srcPath = path5.join(src, entry.name);
2984
- const destPath = path5.join(dest, entry.name);
3468
+ const srcPath = path8.join(src, entry.name);
3469
+ const destPath = path8.join(dest, entry.name);
2985
3470
  if (entry.isDirectory()) {
2986
3471
  copyDir(srcPath, destPath);
2987
3472
  } else {
2988
- fs3.copyFileSync(srcPath, destPath);
3473
+ fs6.copyFileSync(srcPath, destPath);
2989
3474
  }
2990
3475
  }
2991
3476
  }
@@ -2993,45 +3478,45 @@ function copyDir(src, dest) {
2993
3478
  // src/server/prod-server.ts
2994
3479
  init_esm_shims();
2995
3480
  import http2 from "http";
2996
- import fs4 from "fs";
2997
- import path6 from "path";
2998
- import pc3 from "picocolors";
3481
+ import fs7 from "fs";
3482
+ import path9 from "path";
3483
+ import pc4 from "picocolors";
2999
3484
  import mime2 from "mime-types";
3000
3485
  var cachedRoutes = [];
3001
3486
  var pageCache = /* @__PURE__ */ new Map();
3002
3487
  async function startProductionServer(options) {
3003
3488
  const { port, host } = options;
3004
3489
  const rootDir = process.cwd();
3005
- const distDir = path6.join(rootDir, ".float");
3006
- const publicDir = path6.join(rootDir, "public");
3007
- const manifestPath = path6.join(distDir, "routes-manifest.json");
3008
- if (fs4.existsSync(manifestPath)) {
3009
- const manifest = JSON.parse(fs4.readFileSync(manifestPath, "utf-8"));
3490
+ const distDir = path9.join(rootDir, ".float");
3491
+ const publicDir = path9.join(rootDir, "public");
3492
+ const manifestPath = path9.join(distDir, "routes-manifest.json");
3493
+ if (fs7.existsSync(manifestPath)) {
3494
+ const manifest = JSON.parse(fs7.readFileSync(manifestPath, "utf-8"));
3010
3495
  cachedRoutes = manifest.routes;
3011
- console.log(pc3.dim(` \u{1F4E6} Loaded ${cachedRoutes.length} routes from manifest`));
3496
+ console.log(pc4.dim(` \u{1F4E6} Loaded ${cachedRoutes.length} routes from manifest`));
3012
3497
  } else {
3013
- console.error(pc3.red(" \u274C No build manifest found. Run `float build` first."));
3498
+ console.error(pc4.red(" \u274C No build manifest found. Run `float build` first."));
3014
3499
  process.exit(1);
3015
3500
  }
3016
- const pagesDir = path6.join(distDir, "pages");
3017
- if (fs4.existsSync(pagesDir)) {
3018
- const prerenderedFiles = fs4.readdirSync(pagesDir, { recursive: true });
3501
+ const pagesDir = path9.join(distDir, "pages");
3502
+ if (fs7.existsSync(pagesDir)) {
3503
+ const prerenderedFiles = fs7.readdirSync(pagesDir, { recursive: true });
3019
3504
  for (const file of prerenderedFiles) {
3020
3505
  if (file.endsWith(".html")) {
3021
3506
  const routePath = "/" + file.replace(/\.html$/, "").replace(/index$/, "");
3022
- const content = fs4.readFileSync(path6.join(pagesDir, file), "utf-8");
3507
+ const content = fs7.readFileSync(path9.join(pagesDir, file), "utf-8");
3023
3508
  pageCache.set(routePath, content);
3024
3509
  }
3025
3510
  }
3026
- console.log(pc3.dim(` \u{1F4C4} Loaded ${pageCache.size} pre-rendered pages`));
3511
+ console.log(pc4.dim(` \u{1F4C4} Loaded ${pageCache.size} pre-rendered pages`));
3027
3512
  }
3028
3513
  const server = http2.createServer(async (req, res) => {
3029
3514
  const url = new URL(req.url || "/", `http://${host}:${port}`);
3030
3515
  const pathname = url.pathname;
3031
3516
  try {
3032
- const staticPath = path6.join(distDir, "static", pathname);
3033
- if (fs4.existsSync(staticPath) && fs4.statSync(staticPath).isFile()) {
3034
- const content = fs4.readFileSync(staticPath);
3517
+ const staticPath = path9.join(distDir, "static", pathname);
3518
+ if (fs7.existsSync(staticPath) && fs7.statSync(staticPath).isFile()) {
3519
+ const content = fs7.readFileSync(staticPath);
3035
3520
  const contentType = mime2.lookup(staticPath) || "application/octet-stream";
3036
3521
  res.writeHead(200, {
3037
3522
  "Content-Type": contentType,
@@ -3040,9 +3525,9 @@ async function startProductionServer(options) {
3040
3525
  res.end(content);
3041
3526
  return;
3042
3527
  }
3043
- const publicFilePath = path6.join(publicDir, pathname);
3044
- if (fs4.existsSync(publicFilePath) && fs4.statSync(publicFilePath).isFile()) {
3045
- const content = fs4.readFileSync(publicFilePath);
3528
+ const publicFilePath = path9.join(publicDir, pathname);
3529
+ if (fs7.existsSync(publicFilePath) && fs7.statSync(publicFilePath).isFile()) {
3530
+ const content = fs7.readFileSync(publicFilePath);
3046
3531
  const contentType = mime2.lookup(publicFilePath) || "application/octet-stream";
3047
3532
  res.writeHead(200, { "Content-Type": contentType });
3048
3533
  res.end(content);
@@ -3075,13 +3560,13 @@ async function startProductionServer(options) {
3075
3560
  });
3076
3561
  res.end(html);
3077
3562
  } catch (error) {
3078
- console.error(pc3.red("Request error:"), error);
3563
+ console.error(pc4.red("Request error:"), error);
3079
3564
  res.writeHead(500, { "Content-Type": "text/html" });
3080
3565
  res.end("<h1>500 - Internal Server Error</h1>");
3081
3566
  }
3082
3567
  });
3083
3568
  server.listen(port, host, () => {
3084
- console.log(pc3.green(` \u2705 Production server running at ${pc3.cyan(`http://${host}:${port}`)}
3569
+ console.log(pc4.green(` \u2705 Production server running at ${pc4.cyan(`http://${host}:${port}`)}
3085
3570
  `));
3086
3571
  });
3087
3572
  }
@@ -3093,14 +3578,14 @@ var VERSION = "2.0.4";
3093
3578
  // src/cli/index.ts
3094
3579
  var cli = cac("float");
3095
3580
  var banner = `
3096
- ${pc4.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")}
3097
- ${pc4.cyan("\u2551")} ${pc4.bold(pc4.magenta("\u26A1 Float.js"))} ${pc4.dim(`v${VERSION}`)} ${pc4.cyan("\u2551")}
3098
- ${pc4.cyan("\u2551")} ${pc4.dim("Ultra Modern Web Framework")} ${pc4.cyan("\u2551")}
3099
- ${pc4.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")}
3581
+ ${pc5.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")}
3582
+ ${pc5.cyan("\u2551")} ${pc5.bold(pc5.magenta("\u26A1 Float.js"))} ${pc5.dim(`v${VERSION}`)} ${pc5.cyan("\u2551")}
3583
+ ${pc5.cyan("\u2551")} ${pc5.dim("Ultra Modern Web Framework")} ${pc5.cyan("\u2551")}
3584
+ ${pc5.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")}
3100
3585
  `;
3101
3586
  cli.command("dev", "Start development server").option("-p, --port <port>", "Port to listen on", { default: 3e3 }).option("-h, --host <host>", "Host to bind to", { default: "localhost" }).option("--open", "Open browser on start", { default: false }).action(async (options) => {
3102
3587
  console.log(banner);
3103
- console.log(pc4.cyan("\u{1F680} Starting development server...\n"));
3588
+ console.log(pc5.cyan("\u{1F680} Starting development server...\n"));
3104
3589
  try {
3105
3590
  const server = await createDevServer({
3106
3591
  port: Number(options.port),
@@ -3109,45 +3594,45 @@ cli.command("dev", "Start development server").option("-p, --port <port>", "Port
3109
3594
  });
3110
3595
  await server.start();
3111
3596
  } catch (error) {
3112
- console.error(pc4.red("\u274C Failed to start dev server:"), error);
3597
+ console.error(pc5.red("\u274C Failed to start dev server:"), error);
3113
3598
  process.exit(1);
3114
3599
  }
3115
3600
  });
3116
3601
  cli.command("build", "Build for production").option("--analyze", "Analyze bundle size", { default: false }).action(async (options) => {
3117
3602
  console.log(banner);
3118
- console.log(pc4.cyan("\u{1F4E6} Building for production...\n"));
3603
+ console.log(pc5.cyan("\u{1F4E6} Building for production...\n"));
3119
3604
  try {
3120
3605
  const startTime = Date.now();
3121
3606
  await build2({ analyze: options.analyze });
3122
3607
  const duration = Date.now() - startTime;
3123
- console.log(pc4.green(`
3608
+ console.log(pc5.green(`
3124
3609
  \u2705 Build completed in ${duration}ms`));
3125
3610
  } catch (error) {
3126
- console.error(pc4.red("\u274C Build failed:"), error);
3611
+ console.error(pc5.red("\u274C Build failed:"), error);
3127
3612
  process.exit(1);
3128
3613
  }
3129
3614
  });
3130
3615
  cli.command("start", "Start production server").option("-p, --port <port>", "Port to listen on", { default: 3e3 }).option("-h, --host <host>", "Host to bind to", { default: "0.0.0.0" }).action(async (options) => {
3131
3616
  console.log(banner);
3132
- console.log(pc4.cyan("\u{1F310} Starting production server...\n"));
3617
+ console.log(pc5.cyan("\u{1F310} Starting production server...\n"));
3133
3618
  try {
3134
3619
  await startProductionServer({
3135
3620
  port: Number(options.port),
3136
3621
  host: options.host
3137
3622
  });
3138
3623
  } catch (error) {
3139
- console.error(pc4.red("\u274C Failed to start server:"), error);
3624
+ console.error(pc5.red("\u274C Failed to start server:"), error);
3140
3625
  process.exit(1);
3141
3626
  }
3142
3627
  });
3143
3628
  cli.command("info", "Show environment information").action(() => {
3144
3629
  console.log(banner);
3145
- console.log(pc4.bold("Environment Info:\n"));
3146
- console.log(` ${pc4.dim("Float.js:")} v${VERSION}`);
3147
- console.log(` ${pc4.dim("Node.js:")} ${process.version}`);
3148
- console.log(` ${pc4.dim("Platform:")} ${process.platform}`);
3149
- console.log(` ${pc4.dim("Arch:")} ${process.arch}`);
3150
- console.log(` ${pc4.dim("CWD:")} ${process.cwd()}`);
3630
+ console.log(pc5.bold("Environment Info:\n"));
3631
+ console.log(` ${pc5.dim("Float.js:")} v${VERSION}`);
3632
+ console.log(` ${pc5.dim("Node.js:")} ${process.version}`);
3633
+ console.log(` ${pc5.dim("Platform:")} ${process.platform}`);
3634
+ console.log(` ${pc5.dim("Arch:")} ${process.arch}`);
3635
+ console.log(` ${pc5.dim("CWD:")} ${process.cwd()}`);
3151
3636
  });
3152
3637
  cli.help();
3153
3638
  cli.version(VERSION);