@teamvelix/velix 5.0.1 → 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 +138 -11
- package/dist/index.js +114 -64
- package/dist/index.js.map +1 -1
- package/dist/runtime/start-dev.js.map +1 -1
- package/dist/runtime/start-prod.js.map +1 -1
- package/dist/server/index.js +84 -34
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,14 +21,68 @@ 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
|
-
## 📦
|
|
24
|
+
## 📦 Installation
|
|
25
|
+
|
|
26
|
+
### Option 1: Create New App (Recommended)
|
|
27
|
+
|
|
28
|
+
The fastest way to get started:
|
|
25
29
|
|
|
26
30
|
```bash
|
|
27
|
-
npx create-velix-app my-app
|
|
31
|
+
npx create-velix-app@latest my-app
|
|
28
32
|
cd my-app
|
|
33
|
+
npm install
|
|
29
34
|
npm run dev
|
|
30
35
|
```
|
|
31
36
|
|
|
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:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Install core framework
|
|
66
|
+
npm install @teamvelix/velix react react-dom
|
|
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
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
32
86
|
## 📁 Project Structure
|
|
33
87
|
|
|
34
88
|
```
|
|
@@ -56,7 +110,7 @@ my-velix-app/
|
|
|
56
110
|
|
|
57
111
|
```ts
|
|
58
112
|
// velix.config.ts
|
|
59
|
-
import { defineConfig } from "velix";
|
|
113
|
+
import { defineConfig } from "@teamvelix/velix";
|
|
60
114
|
|
|
61
115
|
export default defineConfig({
|
|
62
116
|
app: {
|
|
@@ -69,30 +123,57 @@ export default defineConfig({
|
|
|
69
123
|
robots: true,
|
|
70
124
|
openGraph: true
|
|
71
125
|
},
|
|
72
|
-
plugins: [
|
|
126
|
+
plugins: []
|
|
73
127
|
});
|
|
74
128
|
```
|
|
75
129
|
|
|
76
130
|
## 🛠️ CLI Commands
|
|
77
131
|
|
|
132
|
+
### Development
|
|
133
|
+
|
|
78
134
|
```bash
|
|
79
|
-
velix dev # Start
|
|
135
|
+
velix dev # Start development server with hot reload
|
|
80
136
|
velix build # Build for production
|
|
81
137
|
velix start # Start production server
|
|
82
|
-
velix doctor # Health check
|
|
138
|
+
velix doctor # Health check & diagnostics
|
|
139
|
+
velix info # Framework & environment info
|
|
140
|
+
```
|
|
83
141
|
|
|
84
|
-
|
|
142
|
+
### Generators
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
velix g page <name> # Generate a new page
|
|
85
146
|
velix g component <name> # Generate a component
|
|
86
147
|
velix g api <name> # Generate an API route
|
|
87
148
|
velix g layout <name> # Generate a layout
|
|
149
|
+
velix g action <name> # Generate a server action
|
|
88
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
|
+
```
|
|
89
154
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
155
|
+
### Project Creation
|
|
156
|
+
|
|
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
|
|
161
|
+
```
|
|
162
|
+
|
|
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)
|
|
93
174
|
```
|
|
94
175
|
|
|
95
|
-
##
|
|
176
|
+
## 📚 Documentation
|
|
96
177
|
|
|
97
178
|
Comprehensive guides and API references:
|
|
98
179
|
|
|
@@ -102,6 +183,52 @@ Comprehensive guides and API references:
|
|
|
102
183
|
- **[Best Practices](./docs/best-practices.md)** - Development guidelines
|
|
103
184
|
- **[Roadmap](./docs/roadmap.md)** - Upcoming features and plugins
|
|
104
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) |  | Core framework |
|
|
229
|
+
| [create-velix-app](https://npmjs.com/package/create-velix-app) |  | Project scaffolding |
|
|
230
|
+
| [@teamvelix/cli](https://npmjs.com/package/@teamvelix/cli) |  | Command-line interface |
|
|
231
|
+
|
|
105
232
|
## 🤝 Contributing
|
|
106
233
|
|
|
107
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
|
|
26
|
-
import
|
|
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 =
|
|
52
|
-
const resolvedPath =
|
|
53
|
-
if (!resolvedPath.startsWith(publicDir) || !
|
|
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 =
|
|
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
|
|
719
|
-
import
|
|
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,
|
|
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} ${
|
|
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(
|
|
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} ${
|
|
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,20 +1175,68 @@ 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();
|
|
1183
|
-
if (msg && !msg.includes("Rebuilding...")) {
|
|
1214
|
+
if (msg && !msg.includes("Rebuilding...") && !msg.includes("Done in")) {
|
|
1215
|
+
logger_default.info(`Tailwind: ${msg}`);
|
|
1216
|
+
}
|
|
1217
|
+
});
|
|
1218
|
+
watcher.stderr.on("data", (data) => {
|
|
1219
|
+
const msg = data.toString().trim();
|
|
1220
|
+
if (msg && !msg.includes("warn")) {
|
|
1221
|
+
logger_default.warn(`Tailwind: ${msg}`);
|
|
1184
1222
|
}
|
|
1185
1223
|
});
|
|
1186
1224
|
watcher.on("error", (err) => {
|
|
1187
1225
|
logger_default.error("Tailwind watcher error", err);
|
|
1188
1226
|
});
|
|
1189
|
-
|
|
1227
|
+
watcher.on("exit", (code) => {
|
|
1228
|
+
if (code !== 0 && code !== null) {
|
|
1229
|
+
logger_default.error(`Tailwind watcher exited with code ${code}`);
|
|
1230
|
+
}
|
|
1231
|
+
});
|
|
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);
|
|
1190
1240
|
}
|
|
1191
1241
|
}
|
|
1192
1242
|
});
|
|
@@ -2431,7 +2481,7 @@ async function createServer(options = {}) {
|
|
|
2431
2481
|
await loadPlugins(projectRoot, config);
|
|
2432
2482
|
await pluginManager.runHook(PluginHooks.CONFIG, config);
|
|
2433
2483
|
const middlewareFns = await loadMiddleware(projectRoot);
|
|
2434
|
-
const appDir = config.resolvedAppDir ||
|
|
2484
|
+
const appDir = config.resolvedAppDir || path9.join(projectRoot, "app");
|
|
2435
2485
|
const routes = buildRouteTree(appDir);
|
|
2436
2486
|
await pluginManager.runHook(PluginHooks.ROUTES_LOADED, routes);
|
|
2437
2487
|
const startTime = Date.now();
|
|
@@ -2473,7 +2523,7 @@ async function createServer(options = {}) {
|
|
|
2473
2523
|
await serveVelixInternal(pathname, req, res, projectRoot);
|
|
2474
2524
|
return;
|
|
2475
2525
|
}
|
|
2476
|
-
const publicDir = config.resolvedPublicDir ||
|
|
2526
|
+
const publicDir = config.resolvedPublicDir || path9.join(projectRoot, "public");
|
|
2477
2527
|
if (await serveStaticFile(pathname, publicDir, res, isDev)) {
|
|
2478
2528
|
if (isDev) logger_default.request(req.method || "GET", pathname, 200, Date.now() - requestStart, { type: "static" });
|
|
2479
2529
|
return;
|
|
@@ -2542,12 +2592,12 @@ async function createServer(options = {}) {
|
|
|
2542
2592
|
};
|
|
2543
2593
|
}
|
|
2544
2594
|
async function serveStaticFile(pathname, publicDir, res, isDev = false) {
|
|
2545
|
-
const filePath =
|
|
2595
|
+
const filePath = path9.join(publicDir, pathname);
|
|
2546
2596
|
if (!filePath.startsWith(publicDir)) return false;
|
|
2547
|
-
if (!
|
|
2548
|
-
const ext =
|
|
2597
|
+
if (!fs8.existsSync(filePath) || fs8.statSync(filePath).isDirectory()) return false;
|
|
2598
|
+
const ext = path9.extname(filePath);
|
|
2549
2599
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
2550
|
-
const content =
|
|
2600
|
+
const content = fs8.readFileSync(filePath);
|
|
2551
2601
|
res.writeHead(200, {
|
|
2552
2602
|
"Content-Type": contentType,
|
|
2553
2603
|
"Content-Length": content.length,
|
|
@@ -2627,8 +2677,8 @@ async function handlePageRoute(route, routes, req, res, url, config, isDev, proj
|
|
|
2627
2677
|
let LayoutComponent = ({ children }) => React2.createElement(React2.Fragment, null, children);
|
|
2628
2678
|
let layoutParams = route.params;
|
|
2629
2679
|
try {
|
|
2630
|
-
const layoutPath =
|
|
2631
|
-
if (
|
|
2680
|
+
const layoutPath = path9.join(path9.dirname(route.filePath), "layout.tsx");
|
|
2681
|
+
if (fs8.existsSync(layoutPath)) {
|
|
2632
2682
|
const layoutMod = await import(`${pathToFileURL3(layoutPath).href}?t=${Date.now()}`);
|
|
2633
2683
|
if (layoutMod.metadata) {
|
|
2634
2684
|
metadata = { ...layoutMod.metadata, ...metadata };
|
|
@@ -2748,12 +2798,12 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
|
|
|
2748
2798
|
}
|
|
2749
2799
|
if (pathname === "/__velix/logo.webp") {
|
|
2750
2800
|
const __filename2 = fileURLToPath2(import.meta.url);
|
|
2751
|
-
const __dirname2 =
|
|
2752
|
-
const fallbackPath =
|
|
2753
|
-
const logoPath =
|
|
2754
|
-
if (
|
|
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)) {
|
|
2755
2805
|
res.writeHead(200, { "Content-Type": "image/webp", "Cache-Control": "public, max-age=31536000, immutable" });
|
|
2756
|
-
res.end(
|
|
2806
|
+
res.end(fs8.readFileSync(logoPath));
|
|
2757
2807
|
} else {
|
|
2758
2808
|
res.writeHead(404);
|
|
2759
2809
|
res.end();
|
|
@@ -2764,17 +2814,17 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
|
|
|
2764
2814
|
const componentName = pathname.replace("/__velix/islands/", "").replace(".js", "");
|
|
2765
2815
|
try {
|
|
2766
2816
|
const searchDirs = [
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2817
|
+
path9.join(projectRoot, "components"),
|
|
2818
|
+
path9.join(projectRoot, "app"),
|
|
2819
|
+
path9.join(projectRoot, "islands")
|
|
2770
2820
|
];
|
|
2771
2821
|
let componentPath = "";
|
|
2772
2822
|
for (const dir of searchDirs) {
|
|
2773
|
-
if (!
|
|
2774
|
-
const files =
|
|
2823
|
+
if (!fs8.existsSync(dir)) continue;
|
|
2824
|
+
const files = fs8.readdirSync(dir, { recursive: true });
|
|
2775
2825
|
const found = files.find((f) => f.replace(/\\/g, "/").endsWith(`${componentName}.tsx`) || f.replace(/\\/g, "/").endsWith(`${componentName}.jsx`));
|
|
2776
2826
|
if (found) {
|
|
2777
|
-
componentPath =
|
|
2827
|
+
componentPath = path9.join(dir, found);
|
|
2778
2828
|
break;
|
|
2779
2829
|
}
|
|
2780
2830
|
}
|
|
@@ -2854,32 +2904,32 @@ init_esm_shims();
|
|
|
2854
2904
|
var CacheManager = class {
|
|
2855
2905
|
cache = /* @__PURE__ */ new Map();
|
|
2856
2906
|
tagIndex = /* @__PURE__ */ new Map();
|
|
2857
|
-
set(
|
|
2907
|
+
set(path11, data, tags = []) {
|
|
2858
2908
|
const entry = {
|
|
2859
|
-
path:
|
|
2909
|
+
path: path11,
|
|
2860
2910
|
tags: new Set(tags),
|
|
2861
2911
|
timestamp: Date.now(),
|
|
2862
2912
|
data
|
|
2863
2913
|
};
|
|
2864
|
-
this.cache.set(
|
|
2914
|
+
this.cache.set(path11, entry);
|
|
2865
2915
|
tags.forEach((tag) => {
|
|
2866
2916
|
if (!this.tagIndex.has(tag)) {
|
|
2867
2917
|
this.tagIndex.set(tag, /* @__PURE__ */ new Set());
|
|
2868
2918
|
}
|
|
2869
|
-
this.tagIndex.get(tag).add(
|
|
2919
|
+
this.tagIndex.get(tag).add(path11);
|
|
2870
2920
|
});
|
|
2871
2921
|
}
|
|
2872
|
-
get(
|
|
2873
|
-
const entry = this.cache.get(
|
|
2922
|
+
get(path11) {
|
|
2923
|
+
const entry = this.cache.get(path11);
|
|
2874
2924
|
return entry ? entry.data : null;
|
|
2875
2925
|
}
|
|
2876
|
-
revalidatePath(
|
|
2877
|
-
this.cache.delete(
|
|
2926
|
+
revalidatePath(path11) {
|
|
2927
|
+
this.cache.delete(path11);
|
|
2878
2928
|
}
|
|
2879
2929
|
revalidateTag(tag) {
|
|
2880
2930
|
const paths = this.tagIndex.get(tag);
|
|
2881
2931
|
if (paths) {
|
|
2882
|
-
paths.forEach((
|
|
2932
|
+
paths.forEach((path11) => this.cache.delete(path11));
|
|
2883
2933
|
this.tagIndex.delete(tag);
|
|
2884
2934
|
}
|
|
2885
2935
|
}
|
|
@@ -2887,17 +2937,17 @@ var CacheManager = class {
|
|
|
2887
2937
|
this.cache.clear();
|
|
2888
2938
|
this.tagIndex.clear();
|
|
2889
2939
|
}
|
|
2890
|
-
has(
|
|
2891
|
-
return this.cache.has(
|
|
2940
|
+
has(path11) {
|
|
2941
|
+
return this.cache.has(path11);
|
|
2892
2942
|
}
|
|
2893
2943
|
};
|
|
2894
2944
|
var cacheManager = new CacheManager();
|
|
2895
|
-
function revalidatePath(
|
|
2896
|
-
cacheManager.revalidatePath(
|
|
2945
|
+
function revalidatePath(path11, type = "path") {
|
|
2946
|
+
cacheManager.revalidatePath(path11);
|
|
2897
2947
|
if (typeof global !== "undefined" && global.__VELIX_HMR_SERVER__) {
|
|
2898
2948
|
global.__VELIX_HMR_SERVER__.broadcast(JSON.stringify({
|
|
2899
2949
|
type: "revalidate",
|
|
2900
|
-
path:
|
|
2950
|
+
path: path11,
|
|
2901
2951
|
revalidationType: type
|
|
2902
2952
|
}));
|
|
2903
2953
|
}
|
|
@@ -3165,8 +3215,8 @@ Image.displayName = "Image";
|
|
|
3165
3215
|
// build/index.ts
|
|
3166
3216
|
init_esm_shims();
|
|
3167
3217
|
import esbuild2 from "esbuild";
|
|
3168
|
-
import
|
|
3169
|
-
import
|
|
3218
|
+
import fs9 from "fs";
|
|
3219
|
+
import path10 from "path";
|
|
3170
3220
|
async function build(options = {}) {
|
|
3171
3221
|
const projectRoot = options.projectRoot || process.cwd();
|
|
3172
3222
|
const config = await loadConfig(projectRoot);
|
|
@@ -3185,7 +3235,7 @@ async function build(options = {}) {
|
|
|
3185
3235
|
return;
|
|
3186
3236
|
}
|
|
3187
3237
|
try {
|
|
3188
|
-
const serverOutDir =
|
|
3238
|
+
const serverOutDir = path10.join(outDir, "server");
|
|
3189
3239
|
ensureDir(serverOutDir);
|
|
3190
3240
|
await esbuild2.build({
|
|
3191
3241
|
entryPoints: sourceFiles,
|
|
@@ -3205,10 +3255,10 @@ async function build(options = {}) {
|
|
|
3205
3255
|
process.exit(1);
|
|
3206
3256
|
}
|
|
3207
3257
|
try {
|
|
3208
|
-
const clientOutDir =
|
|
3258
|
+
const clientOutDir = path10.join(outDir, "client");
|
|
3209
3259
|
ensureDir(clientOutDir);
|
|
3210
3260
|
const clientFiles = sourceFiles.filter((f) => {
|
|
3211
|
-
const content =
|
|
3261
|
+
const content = fs9.readFileSync(f, "utf-8");
|
|
3212
3262
|
const firstLine = content.split("\n")[0]?.trim();
|
|
3213
3263
|
return firstLine === "'use client'" || firstLine === '"use client"' || firstLine === "'use island'" || firstLine === '"use island"';
|
|
3214
3264
|
});
|
|
@@ -3234,8 +3284,8 @@ async function build(options = {}) {
|
|
|
3234
3284
|
process.exit(1);
|
|
3235
3285
|
}
|
|
3236
3286
|
const publicDir = resolved.resolvedPublicDir;
|
|
3237
|
-
if (
|
|
3238
|
-
const publicOutDir =
|
|
3287
|
+
if (fs9.existsSync(publicDir)) {
|
|
3288
|
+
const publicOutDir = path10.join(outDir, "public");
|
|
3239
3289
|
ensureDir(publicOutDir);
|
|
3240
3290
|
copyDirRecursive(publicDir, publicOutDir);
|
|
3241
3291
|
logger_default.success("Static assets copied");
|
|
@@ -3249,7 +3299,7 @@ async function build(options = {}) {
|
|
|
3249
3299
|
})),
|
|
3250
3300
|
api: routes.api.map((r) => ({ path: r.path }))
|
|
3251
3301
|
};
|
|
3252
|
-
|
|
3302
|
+
fs9.writeFileSync(path10.join(outDir, "manifest.json"), JSON.stringify(manifest, null, 2));
|
|
3253
3303
|
const elapsed = Date.now() - startTime;
|
|
3254
3304
|
const totalSize = getDirSize(outDir);
|
|
3255
3305
|
logger_default.blank();
|
|
@@ -3267,22 +3317,22 @@ async function build(options = {}) {
|
|
|
3267
3317
|
}
|
|
3268
3318
|
function copyDirRecursive(src, dest) {
|
|
3269
3319
|
ensureDir(dest);
|
|
3270
|
-
const entries =
|
|
3320
|
+
const entries = fs9.readdirSync(src, { withFileTypes: true });
|
|
3271
3321
|
for (const entry of entries) {
|
|
3272
|
-
const srcPath =
|
|
3273
|
-
const destPath =
|
|
3322
|
+
const srcPath = path10.join(src, entry.name);
|
|
3323
|
+
const destPath = path10.join(dest, entry.name);
|
|
3274
3324
|
if (entry.isDirectory()) copyDirRecursive(srcPath, destPath);
|
|
3275
|
-
else
|
|
3325
|
+
else fs9.copyFileSync(srcPath, destPath);
|
|
3276
3326
|
}
|
|
3277
3327
|
}
|
|
3278
3328
|
function getDirSize(dir) {
|
|
3279
3329
|
let size = 0;
|
|
3280
|
-
if (!
|
|
3281
|
-
const entries =
|
|
3330
|
+
if (!fs9.existsSync(dir)) return size;
|
|
3331
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
3282
3332
|
for (const entry of entries) {
|
|
3283
|
-
const fullPath =
|
|
3333
|
+
const fullPath = path10.join(dir, entry.name);
|
|
3284
3334
|
if (entry.isDirectory()) size += getDirSize(fullPath);
|
|
3285
|
-
else size +=
|
|
3335
|
+
else size += fs9.statSync(fullPath).size;
|
|
3286
3336
|
}
|
|
3287
3337
|
return size;
|
|
3288
3338
|
}
|