@teamvelix/velix 5.0.2 → 5.0.3

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/README.md CHANGED
@@ -21,7 +21,11 @@ Velix is a lightweight but powerful React 19 framework featuring file-based rout
21
21
  - 📦 **Edge Ready** — Deploy to any edge platform
22
22
  - 🤖 **AI Assistant** — Built-in CLI AI for code generation
23
23
 
24
- ## 📦 Quick Start
24
+ ## 📦 Installation
25
+
26
+ ### Option 1: Create New App (Recommended)
27
+
28
+ The fastest way to get started:
25
29
 
26
30
  ```bash
27
31
  npx create-velix-app@latest my-app
@@ -30,11 +34,53 @@ npm install
30
34
  npm run dev
31
35
  ```
32
36
 
33
- Or install manually:
37
+ This will:
38
+ - ✅ Create a new Velix project with your chosen template
39
+ - ✅ Install all dependencies automatically
40
+ - ✅ Set up Tailwind CSS (optional)
41
+ - ✅ Configure TypeScript
42
+
43
+ ### Option 2: Install CLI Globally
44
+
45
+ For multiple projects or advanced usage:
46
+
47
+ ```bash
48
+ # Install Velix CLI globally
49
+ npm install -g @teamvelix/cli
50
+
51
+ # Create a new project
52
+ velix create my-app
53
+ cd my-app
54
+ npm install
55
+
56
+ # Start development
57
+ velix dev
58
+ ```
59
+
60
+ ### Option 3: Manual Installation
61
+
62
+ Add Velix to an existing project:
34
63
 
35
64
  ```bash
65
+ # Install core framework
36
66
  npm install @teamvelix/velix react react-dom
37
- npm install -D @teamvelix/cli typescript
67
+
68
+ # Install dev dependencies
69
+ npm install -D @teamvelix/cli typescript @types/react @types/react-dom
70
+
71
+ # Optional: Tailwind CSS
72
+ npm install -D tailwindcss postcss autoprefixer
73
+ ```
74
+
75
+ Then create a `velix.config.ts` file:
76
+
77
+ ```ts
78
+ import { defineConfig } from "@teamvelix/velix";
79
+
80
+ export default defineConfig({
81
+ app: { name: "My App" },
82
+ server: { port: 3000 },
83
+ });
38
84
  ```
39
85
 
40
86
  ## 📁 Project Structure
@@ -83,24 +129,51 @@ export default defineConfig({
83
129
 
84
130
  ## 🛠️ CLI Commands
85
131
 
132
+ ### Development
133
+
86
134
  ```bash
87
- velix dev # Start dev server
135
+ velix dev # Start development server with hot reload
88
136
  velix build # Build for production
89
137
  velix start # Start production server
90
- velix doctor # Health check
138
+ velix doctor # Health check & diagnostics
139
+ velix info # Framework & environment info
140
+ ```
91
141
 
92
- velix g page <name> # Generate a page
142
+ ### Generators
143
+
144
+ ```bash
145
+ velix g page <name> # Generate a new page
93
146
  velix g component <name> # Generate a component
94
147
  velix g api <name> # Generate an API route
95
148
  velix g layout <name> # Generate a layout
149
+ velix g action <name> # Generate a server action
96
150
  velix g middleware <name> # Generate middleware
151
+ velix g hook <name> # Generate a custom hook
152
+ velix g context <name> # Generate a React context
153
+ ```
154
+
155
+ ### Project Creation
97
156
 
98
- velix ai start # Launch AI assistant
99
- velix analyze # Bundle analysis
100
- velix info # Framework info
157
+ ```bash
158
+ velix create <name> # Create new project (interactive)
159
+ velix create <name> --template=minimal # Use minimal template
160
+ velix create <name> --no-tailwind # Skip Tailwind CSS
101
161
  ```
102
162
 
103
- ## Documentation
163
+ ### UI Components (Shadcn-style)
164
+
165
+ ```bash
166
+ velix ui add button # Add button component
167
+ # More components coming soon
168
+ ```
169
+
170
+ ### Other
171
+
172
+ ```bash
173
+ velix analyze # Bundle analysis (coming soon)
174
+ ```
175
+
176
+ ## 📚 Documentation
104
177
 
105
178
  Comprehensive guides and API references:
106
179
 
@@ -110,6 +183,52 @@ Comprehensive guides and API references:
110
183
  - **[Best Practices](./docs/best-practices.md)** - Development guidelines
111
184
  - **[Roadmap](./docs/roadmap.md)** - Upcoming features and plugins
112
185
 
186
+ ## 🔧 Troubleshooting
187
+
188
+ ### Common Issues
189
+
190
+ **Module not found errors:**
191
+ ```bash
192
+ # Clear node_modules and reinstall
193
+ rm -rf node_modules package-lock.json
194
+ npm install
195
+ ```
196
+
197
+ **Tailwind CSS not working:**
198
+ ```bash
199
+ # Ensure Tailwind is installed
200
+ npm install -D tailwindcss postcss autoprefixer
201
+
202
+ # Check that velix.config.ts includes tailwindPlugin
203
+ import { defineConfig, tailwindPlugin } from "@teamvelix/velix";
204
+
205
+ export default defineConfig({
206
+ plugins: [tailwindPlugin()]
207
+ });
208
+ ```
209
+
210
+ **Port already in use:**
211
+ ```bash
212
+ # Change port in velix.config.ts
213
+ export default defineConfig({
214
+ server: { port: 3001 }
215
+ });
216
+ ```
217
+
218
+ ### Getting Help
219
+
220
+ - 📖 Check the [documentation](./docs/README.md)
221
+ - 💬 Join our [Discord community](https://discord.gg/velix)
222
+ - 🐛 Report bugs on [GitHub Issues](https://github.com/Velixteam/velix/issues)
223
+
224
+ ## 📦 NPM Packages
225
+
226
+ | Package | Version | Description |
227
+ |---------|---------|-------------|
228
+ | [@teamvelix/velix](https://npmjs.com/package/@teamvelix/velix) | ![npm](https://img.shields.io/npm/v/@teamvelix/velix) | Core framework |
229
+ | [create-velix-app](https://npmjs.com/package/create-velix-app) | ![npm](https://img.shields.io/npm/v/create-velix-app) | Project scaffolding |
230
+ | [@teamvelix/cli](https://npmjs.com/package/@teamvelix/cli) | ![npm](https://img.shields.io/npm/v/@teamvelix/cli) | Command-line interface |
231
+
113
232
  ## 🤝 Contributing
114
233
 
115
234
  We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for details.
package/dist/index.js CHANGED
@@ -22,8 +22,8 @@ var image_optimizer_exports = {};
22
22
  __export(image_optimizer_exports, {
23
23
  handleImageOptimization: () => handleImageOptimization
24
24
  });
25
- import fs6 from "fs";
26
- import path7 from "path";
25
+ import fs7 from "fs";
26
+ import path8 from "path";
27
27
  async function handleImageOptimization(req, res, projectRoot) {
28
28
  let sharp;
29
29
  try {
@@ -48,14 +48,14 @@ async function handleImageOptimization(req, res, projectRoot) {
48
48
  if (!response.ok) throw new Error(`Failed to fetch ${imageUrl}`);
49
49
  imageBuffer = Buffer.from(await response.arrayBuffer());
50
50
  } else {
51
- const publicDir = path7.join(projectRoot, "public");
52
- const resolvedPath = path7.join(publicDir, imageUrl.startsWith("/") ? imageUrl.slice(1) : imageUrl);
53
- if (!resolvedPath.startsWith(publicDir) || !fs6.existsSync(resolvedPath)) {
51
+ const publicDir = path8.join(projectRoot, "public");
52
+ const resolvedPath = path8.join(publicDir, imageUrl.startsWith("/") ? imageUrl.slice(1) : imageUrl);
53
+ if (!resolvedPath.startsWith(publicDir) || !fs7.existsSync(resolvedPath)) {
54
54
  res.writeHead(404);
55
55
  res.end("Image not found");
56
56
  return;
57
57
  }
58
- imageBuffer = fs6.readFileSync(resolvedPath);
58
+ imageBuffer = fs7.readFileSync(resolvedPath);
59
59
  }
60
60
  if (!sharp) {
61
61
  res.writeHead(200, {
@@ -715,8 +715,8 @@ function buildTree(routes) {
715
715
  // server/index.ts
716
716
  init_esm_shims();
717
717
  import http from "http";
718
- import fs7 from "fs";
719
- import path8 from "path";
718
+ import fs8 from "fs";
719
+ import path9 from "path";
720
720
  import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL3 } from "url";
721
721
  import React2 from "react";
722
722
  import { renderToString } from "react-dom/server";
@@ -1026,6 +1026,8 @@ var builtinPlugins = {
1026
1026
  // plugins/tailwind.ts
1027
1027
  init_esm_shims();
1028
1028
  import { spawnSync, spawn } from "child_process";
1029
+ import fs6 from "fs";
1030
+ import path7 from "path";
1029
1031
 
1030
1032
  // logger.ts
1031
1033
  init_esm_shims();
@@ -1077,14 +1079,14 @@ var logger = {
1077
1079
  if (pagesDir) console.log(` ${c.bold}App:${c.reset} ${c.dim}${pagesDir}${c.reset}`);
1078
1080
  console.log("");
1079
1081
  },
1080
- request(method, path10, status, time, extra = {}) {
1082
+ request(method, path11, status, time, extra = {}) {
1081
1083
  const statusColor = getStatusColor(status);
1082
1084
  const timeStr = fmtTime(time);
1083
1085
  let badge = `${c.dim}\u25CB${c.reset}`;
1084
1086
  if (extra.type === "dynamic" || extra.type === "ssr") badge = `${c.white}\u0192${c.reset}`;
1085
1087
  else if (extra.type === "api") badge = `${c.cyan}\u03BB${c.reset}`;
1086
1088
  const statusStr = `${statusColor}${status}${c.reset}`;
1087
- console.log(` ${badge} ${c.white}${method}${c.reset} ${path10} ${statusStr} ${c.dim}${timeStr}${c.reset}`);
1089
+ console.log(` ${badge} ${c.white}${method}${c.reset} ${path11} ${statusStr} ${c.dim}${timeStr}${c.reset}`);
1088
1090
  },
1089
1091
  info(msg) {
1090
1092
  console.log(` ${c.cyan}\u2139${c.reset} ${msg}`);
@@ -1112,10 +1114,10 @@ var logger = {
1112
1114
  plugin(name) {
1113
1115
  console.log(` ${c.cyan}\u25C6${c.reset} Plugin ${c.dim}${name}${c.reset}`);
1114
1116
  },
1115
- route(path10, type) {
1117
+ route(path11, type) {
1116
1118
  const typeLabel = type === "api" ? "\u03BB" : type === "dynamic" ? "\u0192" : "\u25CB";
1117
1119
  const color = type === "api" ? c.cyan : type === "dynamic" ? c.white : c.dim;
1118
- console.log(` ${color}${typeLabel}${c.reset} ${path10}`);
1120
+ console.log(` ${color}${typeLabel}${c.reset} ${path11}`);
1119
1121
  },
1120
1122
  divider() {
1121
1123
  console.log(`${c.dim} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}`);
@@ -1173,10 +1175,39 @@ function tailwindPlugin(options = {}) {
1173
1175
  },
1174
1176
  [PluginHooks.SERVER_START]: async (server, isDev) => {
1175
1177
  if (!isDev) return;
1178
+ if (!fs6.existsSync(input)) {
1179
+ logger_default.warn(`Tailwind input file not found: ${input}`);
1180
+ return;
1181
+ }
1182
+ const outputDir = path7.dirname(output);
1183
+ if (!fs6.existsSync(outputDir)) {
1184
+ fs6.mkdirSync(outputDir, { recursive: true });
1185
+ }
1186
+ logger_default.info("Building initial Tailwind CSS...");
1187
+ try {
1188
+ const buildResult = spawnSync("npx", ["tailwindcss", "-i", input, "-o", output], {
1189
+ cwd: process.cwd(),
1190
+ stdio: "pipe"
1191
+ });
1192
+ if (buildResult.error) {
1193
+ logger_default.error("Tailwind CSS not installed. Run: npm install -D tailwindcss");
1194
+ return;
1195
+ }
1196
+ if (buildResult.status !== 0) {
1197
+ const errorMsg = buildResult.stderr?.toString() || "Unknown error";
1198
+ logger_default.error(`Tailwind build failed: ${errorMsg}`);
1199
+ return;
1200
+ }
1201
+ logger_default.success("Tailwind CSS built successfully");
1202
+ } catch (err) {
1203
+ logger_default.error("Failed to build Tailwind CSS", err);
1204
+ return;
1205
+ }
1176
1206
  logger_default.info("Starting Tailwind CSS watcher...");
1177
1207
  const watcher = spawn("npx", ["tailwindcss", "-i", input, "-o", output, "--watch"], {
1178
1208
  stdio: "pipe",
1179
- cwd: process.cwd()
1209
+ cwd: process.cwd(),
1210
+ shell: false
1180
1211
  });
1181
1212
  watcher.stdout.on("data", (data) => {
1182
1213
  const msg = data.toString().trim();
@@ -1186,7 +1217,7 @@ function tailwindPlugin(options = {}) {
1186
1217
  });
1187
1218
  watcher.stderr.on("data", (data) => {
1188
1219
  const msg = data.toString().trim();
1189
- if (msg) {
1220
+ if (msg && !msg.includes("warn")) {
1190
1221
  logger_default.warn(`Tailwind: ${msg}`);
1191
1222
  }
1192
1223
  });
@@ -1198,9 +1229,14 @@ function tailwindPlugin(options = {}) {
1198
1229
  logger_default.error(`Tailwind watcher exited with code ${code}`);
1199
1230
  }
1200
1231
  });
1201
- process.on("exit", () => watcher.kill());
1202
- process.on("SIGINT", () => watcher.kill());
1203
- process.on("SIGTERM", () => watcher.kill());
1232
+ const cleanup = () => {
1233
+ if (watcher && !watcher.killed) {
1234
+ watcher.kill();
1235
+ }
1236
+ };
1237
+ process.on("exit", cleanup);
1238
+ process.on("SIGINT", cleanup);
1239
+ process.on("SIGTERM", cleanup);
1204
1240
  }
1205
1241
  }
1206
1242
  });
@@ -2445,7 +2481,7 @@ async function createServer(options = {}) {
2445
2481
  await loadPlugins(projectRoot, config);
2446
2482
  await pluginManager.runHook(PluginHooks.CONFIG, config);
2447
2483
  const middlewareFns = await loadMiddleware(projectRoot);
2448
- const appDir = config.resolvedAppDir || path8.join(projectRoot, "app");
2484
+ const appDir = config.resolvedAppDir || path9.join(projectRoot, "app");
2449
2485
  const routes = buildRouteTree(appDir);
2450
2486
  await pluginManager.runHook(PluginHooks.ROUTES_LOADED, routes);
2451
2487
  const startTime = Date.now();
@@ -2487,7 +2523,7 @@ async function createServer(options = {}) {
2487
2523
  await serveVelixInternal(pathname, req, res, projectRoot);
2488
2524
  return;
2489
2525
  }
2490
- const publicDir = config.resolvedPublicDir || path8.join(projectRoot, "public");
2526
+ const publicDir = config.resolvedPublicDir || path9.join(projectRoot, "public");
2491
2527
  if (await serveStaticFile(pathname, publicDir, res, isDev)) {
2492
2528
  if (isDev) logger_default.request(req.method || "GET", pathname, 200, Date.now() - requestStart, { type: "static" });
2493
2529
  return;
@@ -2556,12 +2592,12 @@ async function createServer(options = {}) {
2556
2592
  };
2557
2593
  }
2558
2594
  async function serveStaticFile(pathname, publicDir, res, isDev = false) {
2559
- const filePath = path8.join(publicDir, pathname);
2595
+ const filePath = path9.join(publicDir, pathname);
2560
2596
  if (!filePath.startsWith(publicDir)) return false;
2561
- if (!fs7.existsSync(filePath) || fs7.statSync(filePath).isDirectory()) return false;
2562
- const ext = path8.extname(filePath);
2597
+ if (!fs8.existsSync(filePath) || fs8.statSync(filePath).isDirectory()) return false;
2598
+ const ext = path9.extname(filePath);
2563
2599
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
2564
- const content = fs7.readFileSync(filePath);
2600
+ const content = fs8.readFileSync(filePath);
2565
2601
  res.writeHead(200, {
2566
2602
  "Content-Type": contentType,
2567
2603
  "Content-Length": content.length,
@@ -2641,8 +2677,8 @@ async function handlePageRoute(route, routes, req, res, url, config, isDev, proj
2641
2677
  let LayoutComponent = ({ children }) => React2.createElement(React2.Fragment, null, children);
2642
2678
  let layoutParams = route.params;
2643
2679
  try {
2644
- const layoutPath = path8.join(path8.dirname(route.filePath), "layout.tsx");
2645
- if (fs7.existsSync(layoutPath)) {
2680
+ const layoutPath = path9.join(path9.dirname(route.filePath), "layout.tsx");
2681
+ if (fs8.existsSync(layoutPath)) {
2646
2682
  const layoutMod = await import(`${pathToFileURL3(layoutPath).href}?t=${Date.now()}`);
2647
2683
  if (layoutMod.metadata) {
2648
2684
  metadata = { ...layoutMod.metadata, ...metadata };
@@ -2762,12 +2798,12 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
2762
2798
  }
2763
2799
  if (pathname === "/__velix/logo.webp") {
2764
2800
  const __filename2 = fileURLToPath2(import.meta.url);
2765
- const __dirname2 = path8.dirname(__filename2);
2766
- const fallbackPath = path8.join(path8.dirname(pathToFileURL3(__dirname2).pathname), "..", "assets", "logo.webp");
2767
- const logoPath = fs7.existsSync(fallbackPath) ? fallbackPath : path8.join(process.cwd(), "node_modules", "velix", "assets", "logo.webp");
2768
- if (fs7.existsSync(logoPath)) {
2801
+ const __dirname2 = path9.dirname(__filename2);
2802
+ const fallbackPath = path9.join(path9.dirname(pathToFileURL3(__dirname2).pathname), "..", "assets", "logo.webp");
2803
+ const logoPath = fs8.existsSync(fallbackPath) ? fallbackPath : path9.join(process.cwd(), "node_modules", "velix", "assets", "logo.webp");
2804
+ if (fs8.existsSync(logoPath)) {
2769
2805
  res.writeHead(200, { "Content-Type": "image/webp", "Cache-Control": "public, max-age=31536000, immutable" });
2770
- res.end(fs7.readFileSync(logoPath));
2806
+ res.end(fs8.readFileSync(logoPath));
2771
2807
  } else {
2772
2808
  res.writeHead(404);
2773
2809
  res.end();
@@ -2778,17 +2814,17 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
2778
2814
  const componentName = pathname.replace("/__velix/islands/", "").replace(".js", "");
2779
2815
  try {
2780
2816
  const searchDirs = [
2781
- path8.join(projectRoot, "components"),
2782
- path8.join(projectRoot, "app"),
2783
- path8.join(projectRoot, "islands")
2817
+ path9.join(projectRoot, "components"),
2818
+ path9.join(projectRoot, "app"),
2819
+ path9.join(projectRoot, "islands")
2784
2820
  ];
2785
2821
  let componentPath = "";
2786
2822
  for (const dir of searchDirs) {
2787
- if (!fs7.existsSync(dir)) continue;
2788
- const files = fs7.readdirSync(dir, { recursive: true });
2823
+ if (!fs8.existsSync(dir)) continue;
2824
+ const files = fs8.readdirSync(dir, { recursive: true });
2789
2825
  const found = files.find((f) => f.replace(/\\/g, "/").endsWith(`${componentName}.tsx`) || f.replace(/\\/g, "/").endsWith(`${componentName}.jsx`));
2790
2826
  if (found) {
2791
- componentPath = path8.join(dir, found);
2827
+ componentPath = path9.join(dir, found);
2792
2828
  break;
2793
2829
  }
2794
2830
  }
@@ -2868,32 +2904,32 @@ init_esm_shims();
2868
2904
  var CacheManager = class {
2869
2905
  cache = /* @__PURE__ */ new Map();
2870
2906
  tagIndex = /* @__PURE__ */ new Map();
2871
- set(path10, data, tags = []) {
2907
+ set(path11, data, tags = []) {
2872
2908
  const entry = {
2873
- path: path10,
2909
+ path: path11,
2874
2910
  tags: new Set(tags),
2875
2911
  timestamp: Date.now(),
2876
2912
  data
2877
2913
  };
2878
- this.cache.set(path10, entry);
2914
+ this.cache.set(path11, entry);
2879
2915
  tags.forEach((tag) => {
2880
2916
  if (!this.tagIndex.has(tag)) {
2881
2917
  this.tagIndex.set(tag, /* @__PURE__ */ new Set());
2882
2918
  }
2883
- this.tagIndex.get(tag).add(path10);
2919
+ this.tagIndex.get(tag).add(path11);
2884
2920
  });
2885
2921
  }
2886
- get(path10) {
2887
- const entry = this.cache.get(path10);
2922
+ get(path11) {
2923
+ const entry = this.cache.get(path11);
2888
2924
  return entry ? entry.data : null;
2889
2925
  }
2890
- revalidatePath(path10) {
2891
- this.cache.delete(path10);
2926
+ revalidatePath(path11) {
2927
+ this.cache.delete(path11);
2892
2928
  }
2893
2929
  revalidateTag(tag) {
2894
2930
  const paths = this.tagIndex.get(tag);
2895
2931
  if (paths) {
2896
- paths.forEach((path10) => this.cache.delete(path10));
2932
+ paths.forEach((path11) => this.cache.delete(path11));
2897
2933
  this.tagIndex.delete(tag);
2898
2934
  }
2899
2935
  }
@@ -2901,17 +2937,17 @@ var CacheManager = class {
2901
2937
  this.cache.clear();
2902
2938
  this.tagIndex.clear();
2903
2939
  }
2904
- has(path10) {
2905
- return this.cache.has(path10);
2940
+ has(path11) {
2941
+ return this.cache.has(path11);
2906
2942
  }
2907
2943
  };
2908
2944
  var cacheManager = new CacheManager();
2909
- function revalidatePath(path10, type = "path") {
2910
- cacheManager.revalidatePath(path10);
2945
+ function revalidatePath(path11, type = "path") {
2946
+ cacheManager.revalidatePath(path11);
2911
2947
  if (typeof global !== "undefined" && global.__VELIX_HMR_SERVER__) {
2912
2948
  global.__VELIX_HMR_SERVER__.broadcast(JSON.stringify({
2913
2949
  type: "revalidate",
2914
- path: path10,
2950
+ path: path11,
2915
2951
  revalidationType: type
2916
2952
  }));
2917
2953
  }
@@ -3179,8 +3215,8 @@ Image.displayName = "Image";
3179
3215
  // build/index.ts
3180
3216
  init_esm_shims();
3181
3217
  import esbuild2 from "esbuild";
3182
- import fs8 from "fs";
3183
- import path9 from "path";
3218
+ import fs9 from "fs";
3219
+ import path10 from "path";
3184
3220
  async function build(options = {}) {
3185
3221
  const projectRoot = options.projectRoot || process.cwd();
3186
3222
  const config = await loadConfig(projectRoot);
@@ -3199,7 +3235,7 @@ async function build(options = {}) {
3199
3235
  return;
3200
3236
  }
3201
3237
  try {
3202
- const serverOutDir = path9.join(outDir, "server");
3238
+ const serverOutDir = path10.join(outDir, "server");
3203
3239
  ensureDir(serverOutDir);
3204
3240
  await esbuild2.build({
3205
3241
  entryPoints: sourceFiles,
@@ -3219,10 +3255,10 @@ async function build(options = {}) {
3219
3255
  process.exit(1);
3220
3256
  }
3221
3257
  try {
3222
- const clientOutDir = path9.join(outDir, "client");
3258
+ const clientOutDir = path10.join(outDir, "client");
3223
3259
  ensureDir(clientOutDir);
3224
3260
  const clientFiles = sourceFiles.filter((f) => {
3225
- const content = fs8.readFileSync(f, "utf-8");
3261
+ const content = fs9.readFileSync(f, "utf-8");
3226
3262
  const firstLine = content.split("\n")[0]?.trim();
3227
3263
  return firstLine === "'use client'" || firstLine === '"use client"' || firstLine === "'use island'" || firstLine === '"use island"';
3228
3264
  });
@@ -3248,8 +3284,8 @@ async function build(options = {}) {
3248
3284
  process.exit(1);
3249
3285
  }
3250
3286
  const publicDir = resolved.resolvedPublicDir;
3251
- if (fs8.existsSync(publicDir)) {
3252
- const publicOutDir = path9.join(outDir, "public");
3287
+ if (fs9.existsSync(publicDir)) {
3288
+ const publicOutDir = path10.join(outDir, "public");
3253
3289
  ensureDir(publicOutDir);
3254
3290
  copyDirRecursive(publicDir, publicOutDir);
3255
3291
  logger_default.success("Static assets copied");
@@ -3263,7 +3299,7 @@ async function build(options = {}) {
3263
3299
  })),
3264
3300
  api: routes.api.map((r) => ({ path: r.path }))
3265
3301
  };
3266
- fs8.writeFileSync(path9.join(outDir, "manifest.json"), JSON.stringify(manifest, null, 2));
3302
+ fs9.writeFileSync(path10.join(outDir, "manifest.json"), JSON.stringify(manifest, null, 2));
3267
3303
  const elapsed = Date.now() - startTime;
3268
3304
  const totalSize = getDirSize(outDir);
3269
3305
  logger_default.blank();
@@ -3281,22 +3317,22 @@ async function build(options = {}) {
3281
3317
  }
3282
3318
  function copyDirRecursive(src, dest) {
3283
3319
  ensureDir(dest);
3284
- const entries = fs8.readdirSync(src, { withFileTypes: true });
3320
+ const entries = fs9.readdirSync(src, { withFileTypes: true });
3285
3321
  for (const entry of entries) {
3286
- const srcPath = path9.join(src, entry.name);
3287
- const destPath = path9.join(dest, entry.name);
3322
+ const srcPath = path10.join(src, entry.name);
3323
+ const destPath = path10.join(dest, entry.name);
3288
3324
  if (entry.isDirectory()) copyDirRecursive(srcPath, destPath);
3289
- else fs8.copyFileSync(srcPath, destPath);
3325
+ else fs9.copyFileSync(srcPath, destPath);
3290
3326
  }
3291
3327
  }
3292
3328
  function getDirSize(dir) {
3293
3329
  let size = 0;
3294
- if (!fs8.existsSync(dir)) return size;
3295
- const entries = fs8.readdirSync(dir, { withFileTypes: true });
3330
+ if (!fs9.existsSync(dir)) return size;
3331
+ const entries = fs9.readdirSync(dir, { withFileTypes: true });
3296
3332
  for (const entry of entries) {
3297
- const fullPath = path9.join(dir, entry.name);
3333
+ const fullPath = path10.join(dir, entry.name);
3298
3334
  if (entry.isDirectory()) size += getDirSize(fullPath);
3299
- else size += fs8.statSync(fullPath).size;
3335
+ else size += fs9.statSync(fullPath).size;
3300
3336
  }
3301
3337
  return size;
3302
3338
  }