@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 +129 -10
- package/dist/index.js +102 -66
- 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 +72 -36
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/server/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 path7 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 = path7.join(projectRoot, "public");
|
|
52
|
+
const resolvedPath = path7.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, {
|
|
@@ -92,8 +92,8 @@ var init_image_optimizer = __esm({
|
|
|
92
92
|
// server/index.ts
|
|
93
93
|
init_esm_shims();
|
|
94
94
|
import http from "http";
|
|
95
|
-
import
|
|
96
|
-
import
|
|
95
|
+
import fs8 from "fs";
|
|
96
|
+
import path8 from "path";
|
|
97
97
|
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL3 } from "url";
|
|
98
98
|
import React2 from "react";
|
|
99
99
|
import { renderToString } from "react-dom/server";
|
|
@@ -682,6 +682,8 @@ var builtinPlugins = {
|
|
|
682
682
|
// plugins/tailwind.ts
|
|
683
683
|
init_esm_shims();
|
|
684
684
|
import { spawnSync, spawn } from "child_process";
|
|
685
|
+
import fs6 from "fs";
|
|
686
|
+
import path6 from "path";
|
|
685
687
|
|
|
686
688
|
// logger.ts
|
|
687
689
|
init_esm_shims();
|
|
@@ -733,14 +735,14 @@ var logger = {
|
|
|
733
735
|
if (pagesDir) console.log(` ${c.bold}App:${c.reset} ${c.dim}${pagesDir}${c.reset}`);
|
|
734
736
|
console.log("");
|
|
735
737
|
},
|
|
736
|
-
request(method,
|
|
738
|
+
request(method, path9, status, time, extra = {}) {
|
|
737
739
|
const statusColor = getStatusColor(status);
|
|
738
740
|
const timeStr = fmtTime(time);
|
|
739
741
|
let badge = `${c.dim}\u25CB${c.reset}`;
|
|
740
742
|
if (extra.type === "dynamic" || extra.type === "ssr") badge = `${c.white}\u0192${c.reset}`;
|
|
741
743
|
else if (extra.type === "api") badge = `${c.cyan}\u03BB${c.reset}`;
|
|
742
744
|
const statusStr = `${statusColor}${status}${c.reset}`;
|
|
743
|
-
console.log(` ${badge} ${c.white}${method}${c.reset} ${
|
|
745
|
+
console.log(` ${badge} ${c.white}${method}${c.reset} ${path9} ${statusStr} ${c.dim}${timeStr}${c.reset}`);
|
|
744
746
|
},
|
|
745
747
|
info(msg) {
|
|
746
748
|
console.log(` ${c.cyan}\u2139${c.reset} ${msg}`);
|
|
@@ -768,10 +770,10 @@ var logger = {
|
|
|
768
770
|
plugin(name) {
|
|
769
771
|
console.log(` ${c.cyan}\u25C6${c.reset} Plugin ${c.dim}${name}${c.reset}`);
|
|
770
772
|
},
|
|
771
|
-
route(
|
|
773
|
+
route(path9, type) {
|
|
772
774
|
const typeLabel = type === "api" ? "\u03BB" : type === "dynamic" ? "\u0192" : "\u25CB";
|
|
773
775
|
const color = type === "api" ? c.cyan : type === "dynamic" ? c.white : c.dim;
|
|
774
|
-
console.log(` ${color}${typeLabel}${c.reset} ${
|
|
776
|
+
console.log(` ${color}${typeLabel}${c.reset} ${path9}`);
|
|
775
777
|
},
|
|
776
778
|
divider() {
|
|
777
779
|
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}`);
|
|
@@ -829,10 +831,39 @@ function tailwindPlugin(options = {}) {
|
|
|
829
831
|
},
|
|
830
832
|
[PluginHooks.SERVER_START]: async (server, isDev) => {
|
|
831
833
|
if (!isDev) return;
|
|
834
|
+
if (!fs6.existsSync(input)) {
|
|
835
|
+
logger_default.warn(`Tailwind input file not found: ${input}`);
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
const outputDir = path6.dirname(output);
|
|
839
|
+
if (!fs6.existsSync(outputDir)) {
|
|
840
|
+
fs6.mkdirSync(outputDir, { recursive: true });
|
|
841
|
+
}
|
|
842
|
+
logger_default.info("Building initial Tailwind CSS...");
|
|
843
|
+
try {
|
|
844
|
+
const buildResult = spawnSync("npx", ["tailwindcss", "-i", input, "-o", output], {
|
|
845
|
+
cwd: process.cwd(),
|
|
846
|
+
stdio: "pipe"
|
|
847
|
+
});
|
|
848
|
+
if (buildResult.error) {
|
|
849
|
+
logger_default.error("Tailwind CSS not installed. Run: npm install -D tailwindcss");
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
if (buildResult.status !== 0) {
|
|
853
|
+
const errorMsg = buildResult.stderr?.toString() || "Unknown error";
|
|
854
|
+
logger_default.error(`Tailwind build failed: ${errorMsg}`);
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
logger_default.success("Tailwind CSS built successfully");
|
|
858
|
+
} catch (err) {
|
|
859
|
+
logger_default.error("Failed to build Tailwind CSS", err);
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
832
862
|
logger_default.info("Starting Tailwind CSS watcher...");
|
|
833
863
|
const watcher = spawn("npx", ["tailwindcss", "-i", input, "-o", output, "--watch"], {
|
|
834
864
|
stdio: "pipe",
|
|
835
|
-
cwd: process.cwd()
|
|
865
|
+
cwd: process.cwd(),
|
|
866
|
+
shell: false
|
|
836
867
|
});
|
|
837
868
|
watcher.stdout.on("data", (data) => {
|
|
838
869
|
const msg = data.toString().trim();
|
|
@@ -842,7 +873,7 @@ function tailwindPlugin(options = {}) {
|
|
|
842
873
|
});
|
|
843
874
|
watcher.stderr.on("data", (data) => {
|
|
844
875
|
const msg = data.toString().trim();
|
|
845
|
-
if (msg) {
|
|
876
|
+
if (msg && !msg.includes("warn")) {
|
|
846
877
|
logger_default.warn(`Tailwind: ${msg}`);
|
|
847
878
|
}
|
|
848
879
|
});
|
|
@@ -854,9 +885,14 @@ function tailwindPlugin(options = {}) {
|
|
|
854
885
|
logger_default.error(`Tailwind watcher exited with code ${code}`);
|
|
855
886
|
}
|
|
856
887
|
});
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
888
|
+
const cleanup = () => {
|
|
889
|
+
if (watcher && !watcher.killed) {
|
|
890
|
+
watcher.kill();
|
|
891
|
+
}
|
|
892
|
+
};
|
|
893
|
+
process.on("exit", cleanup);
|
|
894
|
+
process.on("SIGINT", cleanup);
|
|
895
|
+
process.on("SIGTERM", cleanup);
|
|
860
896
|
}
|
|
861
897
|
}
|
|
862
898
|
});
|
|
@@ -2031,7 +2067,7 @@ async function createServer(options = {}) {
|
|
|
2031
2067
|
await loadPlugins(projectRoot, config);
|
|
2032
2068
|
await pluginManager.runHook(PluginHooks.CONFIG, config);
|
|
2033
2069
|
const middlewareFns = await loadMiddleware(projectRoot);
|
|
2034
|
-
const appDir = config.resolvedAppDir ||
|
|
2070
|
+
const appDir = config.resolvedAppDir || path8.join(projectRoot, "app");
|
|
2035
2071
|
const routes = buildRouteTree(appDir);
|
|
2036
2072
|
await pluginManager.runHook(PluginHooks.ROUTES_LOADED, routes);
|
|
2037
2073
|
const startTime = Date.now();
|
|
@@ -2073,7 +2109,7 @@ async function createServer(options = {}) {
|
|
|
2073
2109
|
await serveVelixInternal(pathname, req, res, projectRoot);
|
|
2074
2110
|
return;
|
|
2075
2111
|
}
|
|
2076
|
-
const publicDir = config.resolvedPublicDir ||
|
|
2112
|
+
const publicDir = config.resolvedPublicDir || path8.join(projectRoot, "public");
|
|
2077
2113
|
if (await serveStaticFile(pathname, publicDir, res, isDev)) {
|
|
2078
2114
|
if (isDev) logger_default.request(req.method || "GET", pathname, 200, Date.now() - requestStart, { type: "static" });
|
|
2079
2115
|
return;
|
|
@@ -2142,12 +2178,12 @@ async function createServer(options = {}) {
|
|
|
2142
2178
|
};
|
|
2143
2179
|
}
|
|
2144
2180
|
async function serveStaticFile(pathname, publicDir, res, isDev = false) {
|
|
2145
|
-
const filePath =
|
|
2181
|
+
const filePath = path8.join(publicDir, pathname);
|
|
2146
2182
|
if (!filePath.startsWith(publicDir)) return false;
|
|
2147
|
-
if (!
|
|
2148
|
-
const ext =
|
|
2183
|
+
if (!fs8.existsSync(filePath) || fs8.statSync(filePath).isDirectory()) return false;
|
|
2184
|
+
const ext = path8.extname(filePath);
|
|
2149
2185
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
2150
|
-
const content =
|
|
2186
|
+
const content = fs8.readFileSync(filePath);
|
|
2151
2187
|
res.writeHead(200, {
|
|
2152
2188
|
"Content-Type": contentType,
|
|
2153
2189
|
"Content-Length": content.length,
|
|
@@ -2227,8 +2263,8 @@ async function handlePageRoute(route, routes, req, res, url, config, isDev, proj
|
|
|
2227
2263
|
let LayoutComponent = ({ children }) => React2.createElement(React2.Fragment, null, children);
|
|
2228
2264
|
let layoutParams = route.params;
|
|
2229
2265
|
try {
|
|
2230
|
-
const layoutPath =
|
|
2231
|
-
if (
|
|
2266
|
+
const layoutPath = path8.join(path8.dirname(route.filePath), "layout.tsx");
|
|
2267
|
+
if (fs8.existsSync(layoutPath)) {
|
|
2232
2268
|
const layoutMod = await import(`${pathToFileURL3(layoutPath).href}?t=${Date.now()}`);
|
|
2233
2269
|
if (layoutMod.metadata) {
|
|
2234
2270
|
metadata = { ...layoutMod.metadata, ...metadata };
|
|
@@ -2348,12 +2384,12 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
|
|
|
2348
2384
|
}
|
|
2349
2385
|
if (pathname === "/__velix/logo.webp") {
|
|
2350
2386
|
const __filename2 = fileURLToPath2(import.meta.url);
|
|
2351
|
-
const __dirname2 =
|
|
2352
|
-
const fallbackPath =
|
|
2353
|
-
const logoPath =
|
|
2354
|
-
if (
|
|
2387
|
+
const __dirname2 = path8.dirname(__filename2);
|
|
2388
|
+
const fallbackPath = path8.join(path8.dirname(pathToFileURL3(__dirname2).pathname), "..", "assets", "logo.webp");
|
|
2389
|
+
const logoPath = fs8.existsSync(fallbackPath) ? fallbackPath : path8.join(process.cwd(), "node_modules", "velix", "assets", "logo.webp");
|
|
2390
|
+
if (fs8.existsSync(logoPath)) {
|
|
2355
2391
|
res.writeHead(200, { "Content-Type": "image/webp", "Cache-Control": "public, max-age=31536000, immutable" });
|
|
2356
|
-
res.end(
|
|
2392
|
+
res.end(fs8.readFileSync(logoPath));
|
|
2357
2393
|
} else {
|
|
2358
2394
|
res.writeHead(404);
|
|
2359
2395
|
res.end();
|
|
@@ -2364,17 +2400,17 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
|
|
|
2364
2400
|
const componentName = pathname.replace("/__velix/islands/", "").replace(".js", "");
|
|
2365
2401
|
try {
|
|
2366
2402
|
const searchDirs = [
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2403
|
+
path8.join(projectRoot, "components"),
|
|
2404
|
+
path8.join(projectRoot, "app"),
|
|
2405
|
+
path8.join(projectRoot, "islands")
|
|
2370
2406
|
];
|
|
2371
2407
|
let componentPath = "";
|
|
2372
2408
|
for (const dir of searchDirs) {
|
|
2373
|
-
if (!
|
|
2374
|
-
const files =
|
|
2409
|
+
if (!fs8.existsSync(dir)) continue;
|
|
2410
|
+
const files = fs8.readdirSync(dir, { recursive: true });
|
|
2375
2411
|
const found = files.find((f) => f.replace(/\\/g, "/").endsWith(`${componentName}.tsx`) || f.replace(/\\/g, "/").endsWith(`${componentName}.jsx`));
|
|
2376
2412
|
if (found) {
|
|
2377
|
-
componentPath =
|
|
2413
|
+
componentPath = path8.join(dir, found);
|
|
2378
2414
|
break;
|
|
2379
2415
|
}
|
|
2380
2416
|
}
|