@teamvelix/velix 5.1.6 → 5.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.
Files changed (42) hide show
  1. package/README.md +1 -1
  2. package/dist/build/index.js +3 -2
  3. package/dist/chunk-4S5YQJHB.js +11 -0
  4. package/dist/chunk-4S5YQJHB.js.map +1 -0
  5. package/dist/{chunk-TGNK4MY5.js → chunk-DTF3KTLR.js} +116 -53
  6. package/dist/chunk-DTF3KTLR.js.map +1 -0
  7. package/dist/{chunk-OIZNYND3.js → chunk-JI2HJFUT.js} +2 -2
  8. package/dist/chunk-JI2HJFUT.js.map +1 -0
  9. package/dist/{chunk-RFWV4CDG.js → chunk-QIPVMOXL.js} +4 -4
  10. package/dist/chunk-QIPVMOXL.js.map +1 -0
  11. package/dist/{chunk-INOZP2VD.js → chunk-QLFG6PW3.js} +3 -2
  12. package/dist/chunk-QLFG6PW3.js.map +1 -0
  13. package/dist/{chunk-BXDKUP2L.js → chunk-XXPHGRLC.js} +3 -3
  14. package/dist/{chunk-BXDKUP2L.js.map → chunk-XXPHGRLC.js.map} +1 -1
  15. package/dist/client/index.d.ts +2 -1
  16. package/dist/client/index.js +2 -1
  17. package/dist/config.d.ts +2 -2
  18. package/dist/config.js +1 -0
  19. package/dist/{image-optimizer-I6TWWH6W.js → image-optimizer-KPRXE5VI.js} +3 -3
  20. package/dist/image-optimizer-KPRXE5VI.js.map +1 -0
  21. package/dist/index-8CqitL9K.d.ts +300 -0
  22. package/dist/{index-C4udNtpZ.d.ts → index-ChyKLf1W.d.ts} +18 -3
  23. package/dist/index.d.ts +104 -226
  24. package/dist/index.js +12 -6
  25. package/dist/index.js.map +1 -1
  26. package/dist/islands/index.d.ts +22 -10
  27. package/dist/islands/index.js +2 -1
  28. package/dist/runtime/start-build.js +2 -2
  29. package/dist/runtime/start-build.js.map +1 -1
  30. package/dist/runtime/start-dev.js +117 -46
  31. package/dist/runtime/start-dev.js.map +1 -1
  32. package/dist/runtime/start-prod.js +117 -46
  33. package/dist/runtime/start-prod.js.map +1 -1
  34. package/dist/server/index.d.ts +3 -1
  35. package/dist/server/index.js +4 -3
  36. package/package.json +60 -58
  37. package/dist/chunk-INOZP2VD.js.map +0 -1
  38. package/dist/chunk-OIZNYND3.js.map +0 -1
  39. package/dist/chunk-RFWV4CDG.js.map +0 -1
  40. package/dist/chunk-TGNK4MY5.js.map +0 -1
  41. package/dist/image-optimizer-I6TWWH6W.js.map +0 -1
  42. package/dist/index-DYgxL3mE.d.ts +0 -107
package/README.md CHANGED
@@ -146,7 +146,7 @@ velix g component <name> # Generate a component
146
146
  velix g api <name> # Generate an API route
147
147
  velix g layout <name> # Generate a layout
148
148
  velix g action <name> # Generate a server action
149
- velix g middleware <name> # Generate middleware
149
+ velix g proxy <name> # Generate a proxy interceptor
150
150
  velix g hook <name> # Generate a custom hook
151
151
  velix g context <name> # Generate a React context
152
152
  ```
@@ -1,5 +1,6 @@
1
- export { build, build_default as default } from '../chunk-BXDKUP2L.js';
2
- import '../chunk-RFWV4CDG.js';
1
+ export { build, build_default as default } from '../chunk-XXPHGRLC.js';
2
+ import '../chunk-QIPVMOXL.js';
3
3
  import '../chunk-F24Q2MX3.js';
4
+ import '../chunk-4S5YQJHB.js';
4
5
  //# sourceMappingURL=index.js.map
5
6
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,11 @@
1
+ import path from 'path';
2
+ import { fileURLToPath } from 'url';
3
+
4
+ // ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postc_36112cdf9ab6125b194fc7941daee874/node_modules/tsup/assets/esm_shims.js
5
+ var getFilename = () => fileURLToPath(import.meta.url);
6
+ var getDirname = () => path.dirname(getFilename());
7
+ var __dirname$1 = /* @__PURE__ */ getDirname();
8
+
9
+ export { __dirname$1 as __dirname };
10
+ //# sourceMappingURL=chunk-4S5YQJHB.js.map
11
+ //# sourceMappingURL=chunk-4S5YQJHB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postc_36112cdf9ab6125b194fc7941daee874/node_modules/tsup/assets/esm_shims.js"],"names":["__dirname"],"mappings":";;;;AAIA,IAAM,WAAA,GAAc,MAAM,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAA;AACvD,IAAM,UAAA,GAAa,MAAM,IAAA,CAAK,OAAA,CAAQ,aAAa,CAAA;AAE5C,IAAMA,8BAA4B,UAAA","file":"chunk-4S5YQJHB.js","sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n"]}
@@ -1,6 +1,7 @@
1
- import { logger_default, buildRouteTree, matchRoute, VERSION } from './chunk-RFWV4CDG.js';
1
+ import { logger_default, buildRouteTree, matchRoute, VERSION } from './chunk-QIPVMOXL.js';
2
2
  import { loadConfig, resolvePaths } from './chunk-F24Q2MX3.js';
3
- import { getRegisteredIslands, generateAdvancedHydrationScript } from './chunk-OIZNYND3.js';
3
+ import { getRegisteredIslands, generateAdvancedHydrationScript } from './chunk-JI2HJFUT.js';
4
+ import { __dirname as __dirname$1 } from './chunk-4S5YQJHB.js';
4
5
  import http from 'http';
5
6
  import fs4 from 'fs';
6
7
  import path4 from 'path';
@@ -12,6 +13,7 @@ import { renderToString } from 'react-dom/server';
12
13
  import { spawnSync, spawn } from 'child_process';
13
14
  export { useFormStatus } from 'react-dom';
14
15
  import esbuild from 'esbuild';
16
+ export { VelixHttpError, buildApiManifest, defineLoader, defineRoute, handleApiRequest, serverAction as serverAction2 } from '@teamvelix/velix-core';
15
17
 
16
18
  var middlewares = {
17
19
  cors(options = {}) {
@@ -67,20 +69,23 @@ var middlewares = {
67
69
  }
68
70
  };
69
71
  async function loadMiddleware(projectRoot) {
70
- const middlewareDir = path4.join(projectRoot, "middleware");
71
72
  const fns = [];
72
- if (!fs4.existsSync(middlewareDir)) return fns;
73
- const files = fs4.readdirSync(middlewareDir).filter((f) => /\.(ts|js)$/.test(f)).sort();
74
- for (const file of files) {
73
+ const possibleFiles = ["proxy.ts", "proxy.js"];
74
+ for (const file of possibleFiles) {
75
+ const filePath = path4.join(projectRoot, file);
76
+ if (!fs4.existsSync(filePath)) continue;
75
77
  try {
76
- const filePath = path4.join(middlewareDir, file);
77
78
  const { pathToFileURL: pathToFileURL3 } = await import('url');
78
79
  const url = pathToFileURL3(filePath).href;
79
80
  const mod = await import(`${url}?t=${Date.now()}`);
80
- const fn = mod.default || mod.middleware;
81
- if (typeof fn === "function") fns.push(fn);
81
+ const fn = mod.default || mod.proxy || mod.middleware;
82
+ if (typeof fn === "function") {
83
+ fns.push(fn);
84
+ break;
85
+ }
82
86
  } catch (err) {
83
- console.warn(`\u26A0 Failed to load middleware ${file}: ${err.message}`);
87
+ const error = err;
88
+ console.warn(`\u26A0 Failed to load proxy ${file}: ${error.message}`);
84
89
  }
85
90
  }
86
91
  return fns;
@@ -265,11 +270,12 @@ async function loadPlugins(projectRoot, config) {
265
270
  console.warn(`\u26A0 Plugin not found: ${entry}`);
266
271
  }
267
272
  }
268
- } else if (typeof entry === "object" && entry.name) {
273
+ } else if (typeof entry === "object" && entry !== null && "name" in entry) {
269
274
  pluginManager.register(entry);
270
275
  }
271
276
  } catch (err) {
272
- console.warn(`\u26A0 Failed to load plugin: ${err.message}`);
277
+ const error = err;
278
+ console.warn(`\u26A0 Failed to load plugin: ${error?.message || String(error)}`);
273
279
  }
274
280
  }
275
281
  }
@@ -284,10 +290,11 @@ function definePlugin(definition) {
284
290
  name: "velix:security",
285
291
  hooks: {
286
292
  [PluginHooks.RESPONSE]: (_req, res) => {
287
- if (!res.headersSent) {
288
- res.setHeader("X-Content-Type-Options", "nosniff");
289
- res.setHeader("X-Frame-Options", "DENY");
290
- res.setHeader("X-XSS-Protection", "1; mode=block");
293
+ const response = res;
294
+ if (!response.headersSent) {
295
+ response.setHeader("X-Content-Type-Options", "nosniff");
296
+ response.setHeader("X-Frame-Options", "DENY");
297
+ response.setHeader("X-XSS-Protection", "1; mode=block");
291
298
  }
292
299
  }
293
300
  }
@@ -299,7 +306,8 @@ function definePlugin(definition) {
299
306
  name: "velix:logger",
300
307
  hooks: {
301
308
  [PluginHooks.RESPONSE]: (req, _res, duration) => {
302
- console.log(` ${req.method} ${req.url} ${duration}ms`);
309
+ const request = req;
310
+ console.log(` ${request.method} ${request.url} ${duration}ms`);
303
311
  }
304
312
  }
305
313
  })
@@ -325,7 +333,8 @@ function tailwindPlugin(options = {}) {
325
333
  return definePlugin({
326
334
  name: "velix:tailwind",
327
335
  hooks: {
328
- [PluginHooks.CONFIG]: (config) => {
336
+ [PluginHooks.CONFIG]: (configArg) => {
337
+ const config = configArg;
329
338
  const relativeOutput = output.startsWith("./") ? output.substring(1) : output;
330
339
  const stylePath = relativeOutput.startsWith("/public") ? relativeOutput.substring(7) : relativeOutput;
331
340
  if (!config.styles) config.styles = [];
@@ -349,7 +358,8 @@ function tailwindPlugin(options = {}) {
349
358
  logger_default.error("Tailwind build failed", err);
350
359
  }
351
360
  },
352
- [PluginHooks.SERVER_START]: async (server, isDev) => {
361
+ [PluginHooks.SERVER_START]: async (server, isDevArg) => {
362
+ const isDev = isDevArg;
353
363
  if (!isDev) return;
354
364
  if (!fs4.existsSync(input)) {
355
365
  logger_default.warn(`Tailwind input file not found: ${input}`);
@@ -856,7 +866,8 @@ async function executeAction(actionId, args, context) {
856
866
  try {
857
867
  const result = await action(...args);
858
868
  return { success: true, data: result };
859
- } catch (error) {
869
+ } catch (err) {
870
+ const error = err;
860
871
  if (error instanceof RedirectError) return { success: true, redirect: error.url };
861
872
  if (error instanceof NotFoundError) return { success: false, error: "Not found" };
862
873
  return { success: false, error: error.message || "Action failed" };
@@ -878,7 +889,8 @@ async function callServerAction(actionId, args) {
878
889
  window.location.href = result.redirect;
879
890
  }
880
891
  return result;
881
- } catch (error) {
892
+ } catch (err) {
893
+ const error = err;
882
894
  return { success: false, error: error.message || "Network error" };
883
895
  }
884
896
  }
@@ -951,7 +963,8 @@ function formAction(action) {
951
963
  try {
952
964
  const result = await action(formData);
953
965
  return { success: true, data: result };
954
- } catch (error) {
966
+ } catch (err) {
967
+ const error = err;
955
968
  if (error instanceof RedirectError) return { success: true, redirect: error.url };
956
969
  return { success: false, error: error.message };
957
970
  }
@@ -1808,8 +1821,6 @@ function generate500Page(options) {
1808
1821
  </body>
1809
1822
  </html>`;
1810
1823
  }
1811
-
1812
- // server/index.ts
1813
1824
  function getProjectVersion(dep, projectRoot) {
1814
1825
  try {
1815
1826
  const projectRequire = createRequire(pathToFileURL(path4.join(projectRoot, "package.json")).href);
@@ -1891,7 +1902,7 @@ async function createServer(options = {}) {
1891
1902
  return;
1892
1903
  }
1893
1904
  if (pathname === "/__velix/image") {
1894
- const { handleImageOptimization } = await import('./image-optimizer-I6TWWH6W.js');
1905
+ const { handleImageOptimization } = await import('./image-optimizer-KPRXE5VI.js');
1895
1906
  await handleImageOptimization(req, res, projectRoot);
1896
1907
  return;
1897
1908
  }
@@ -1920,13 +1931,14 @@ async function createServer(options = {}) {
1920
1931
  res.end(generate404Page(pathname));
1921
1932
  if (isDev) logger_default.request(req.method || "GET", pathname, 404, Date.now() - requestStart);
1922
1933
  } catch (error) {
1934
+ const err = error;
1923
1935
  console.error("Server error:", error);
1924
1936
  if (!res.headersSent) {
1925
1937
  res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
1926
1938
  res.end(generate500Page({
1927
1939
  title: "Server Error",
1928
- message: error.message || "An unexpected error occurred",
1929
- stack: isDev ? error.stack : void 0,
1940
+ message: err.message || "An unexpected error occurred",
1941
+ stack: isDev ? err.stack : void 0,
1930
1942
  isDev,
1931
1943
  pathname
1932
1944
  }));
@@ -2053,26 +2065,26 @@ async function handleApiRoute(route, req, res, url) {
2053
2065
  res.end(JSON.stringify({ error: "Method not allowed" }));
2054
2066
  return;
2055
2067
  }
2056
- let body;
2068
+ let rawBody;
2057
2069
  if (["POST", "PUT", "PATCH"].includes(method)) {
2058
- body = await parseRequestBody(req);
2070
+ rawBody = await parseRawBody(req);
2059
2071
  }
2060
- const request = {
2061
- method,
2062
- url: req.url,
2063
- headers: req.headers,
2064
- params: route.params || {},
2065
- query: Object.fromEntries(url.searchParams),
2066
- body,
2067
- json: () => body
2068
- };
2069
- const response = await handler(request);
2072
+ const headers2 = new Headers();
2073
+ for (const [key, val] of Object.entries(req.headers)) {
2074
+ if (Array.isArray(val)) val.forEach((v) => headers2.append(key, v));
2075
+ else if (val) headers2.set(key, val);
2076
+ }
2077
+ const reqInit = { method, headers: headers2 };
2078
+ if (rawBody !== void 0) reqInit.body = rawBody;
2079
+ const request = new Request(url.href, reqInit);
2080
+ request.velixUrl = url;
2081
+ const response = await handler(request, { params: route.params || {} });
2070
2082
  if (response instanceof Response) {
2071
- const headers2 = {};
2083
+ const headers3 = {};
2072
2084
  response.headers.forEach((v, k) => {
2073
- headers2[k] = v;
2085
+ headers3[k] = v;
2074
2086
  });
2075
- res.writeHead(response.status, headers2);
2087
+ res.writeHead(response.status, headers3);
2076
2088
  const text2 = await response.text();
2077
2089
  res.end(text2);
2078
2090
  } else if (typeof response === "object") {
@@ -2083,8 +2095,9 @@ async function handleApiRoute(route, req, res, url) {
2083
2095
  res.end(String(response));
2084
2096
  }
2085
2097
  } catch (err) {
2098
+ const error = err;
2086
2099
  res.writeHead(500, { "Content-Type": "application/json" });
2087
- res.end(JSON.stringify({ error: err.message }));
2100
+ res.end(JSON.stringify({ error: error.message }));
2088
2101
  }
2089
2102
  }
2090
2103
  async function handleServerAction(req, res) {
@@ -2100,8 +2113,9 @@ async function handleServerAction(req, res) {
2100
2113
  res.writeHead(200, { "Content-Type": "application/json" });
2101
2114
  res.end(JSON.stringify(result));
2102
2115
  } catch (err) {
2116
+ const error = err;
2103
2117
  res.writeHead(500, { "Content-Type": "application/json" });
2104
- res.end(JSON.stringify({ success: false, error: err.message }));
2118
+ res.end(JSON.stringify({ success: false, error: error.message }));
2105
2119
  }
2106
2120
  }
2107
2121
  async function handlePageRoute(route, routes, req, res, url, config, isDev, projectRoot) {
@@ -2166,9 +2180,14 @@ async function handlePageRoute(route, routes, req, res, url, config, isDev, proj
2166
2180
  const headInjectionsHtml = `
2167
2181
  ${headInjections}
2168
2182
  `;
2183
+ const hmrScript = isDev ? `
2184
+ <script type="module">
2185
+ import { initHMRClient, VelixDevOverlay } from '/__velix/hmr-client.js';
2186
+ initHMRClient();
2187
+ </script>` : "";
2169
2188
  const bodyInjectionsHtml = `
2170
2189
  <div id="__velix-islands"></div>
2171
- ${hydrationScript}${devToolsHtml}
2190
+ ${hydrationScript}${devToolsHtml}${hmrScript}
2172
2191
  `;
2173
2192
  if (finalHtml.includes("<html")) {
2174
2193
  const headEnd = finalHtml.lastIndexOf("</head>");
@@ -2204,12 +2223,13 @@ async function handlePageRoute(route, routes, req, res, url, config, isDev, proj
2204
2223
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
2205
2224
  res.end(finalHtml);
2206
2225
  } catch (err) {
2207
- logger_default.error(`Render error: ${route.path}`, err);
2226
+ const error = err;
2227
+ logger_default.error(`Render error: ${route.path}`, error);
2208
2228
  res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
2209
2229
  res.end(generate500Page({
2210
2230
  title: "Render Error",
2211
- message: err.message || "Failed to render page",
2212
- stack: isDev ? err.stack : void 0,
2231
+ message: error.message || "Failed to render page",
2232
+ stack: isDev ? error.stack : void 0,
2213
2233
  isDev,
2214
2234
  pathname: route.path
2215
2235
  }));
@@ -2252,6 +2272,38 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
2252
2272
  }
2253
2273
  return;
2254
2274
  }
2275
+ if (pathname === "/__velix/hmr-client.js") {
2276
+ try {
2277
+ const candidates = [
2278
+ path4.join(process.cwd(), "packages", "velix-react", "src", "hmr", "hmr-client.ts"),
2279
+ path4.join(process.cwd(), "node_modules", "@teamvelix", "velix-react", "src", "hmr", "hmr-client.ts"),
2280
+ path4.join(__dirname$1, "..", "..", "velix-react", "src", "hmr", "hmr-client.ts")
2281
+ ];
2282
+ const hmrClientSrc = candidates.find((p) => fs4.existsSync(p));
2283
+ if (!hmrClientSrc) {
2284
+ res.writeHead(404);
2285
+ res.end();
2286
+ return;
2287
+ }
2288
+ const result = await esbuild.build({
2289
+ entryPoints: [hmrClientSrc],
2290
+ bundle: true,
2291
+ format: "esm",
2292
+ platform: "browser",
2293
+ target: ["es2022"],
2294
+ minify: true,
2295
+ write: false
2296
+ });
2297
+ res.writeHead(200, { "Content-Type": "application/javascript", "Cache-Control": "no-cache" });
2298
+ res.end(result.outputFiles[0].text);
2299
+ return;
2300
+ } catch (err) {
2301
+ console.error("HMR Client build failed", err);
2302
+ res.writeHead(500);
2303
+ res.end();
2304
+ return;
2305
+ }
2306
+ }
2255
2307
  if (pathname.startsWith("/__velix/islands/") && pathname.endsWith(".js")) {
2256
2308
  const componentName = pathname.replace("/__velix/islands/", "").replace(".js", "");
2257
2309
  try {
@@ -2292,9 +2344,10 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
2292
2344
  res.end(result.outputFiles[0].text);
2293
2345
  return;
2294
2346
  } catch (err) {
2295
- logger_default.error(`Island bundling failed: ${componentName}`, err);
2347
+ const error = err;
2348
+ logger_default.error(`Island bundling failed: ${componentName}`, error);
2296
2349
  res.writeHead(500);
2297
- res.end(`console.error("Island bundling failed: ${err.message}");`);
2350
+ res.end(`console.error("Island bundling failed: ${error.message}");`);
2298
2351
  return;
2299
2352
  }
2300
2353
  }
@@ -2319,7 +2372,7 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
2319
2372
  return;
2320
2373
  }
2321
2374
  }
2322
- res.writeHead(404);
2375
+ res.writeHead(404, { "Content-Type": "text/plain" });
2323
2376
  res.end("Not found");
2324
2377
  }
2325
2378
  function parseRequestBody(req) {
@@ -2340,8 +2393,18 @@ function parseRequestBody(req) {
2340
2393
  req.on("error", reject);
2341
2394
  });
2342
2395
  }
2396
+ function parseRawBody(req) {
2397
+ return new Promise((resolve, reject) => {
2398
+ let body = "";
2399
+ req.on("data", (chunk) => {
2400
+ body += chunk;
2401
+ });
2402
+ req.on("end", () => resolve(body));
2403
+ req.on("error", reject);
2404
+ });
2405
+ }
2343
2406
  var server_default = { createServer, tailwindPlugin };
2344
2407
 
2345
2408
  export { NotFoundError, PluginHooks, PluginManager, RedirectError, bindArgs, callServerAction, composeMiddleware, cookies, createServer, definePlugin, deserializeArgs, executeAction, formAction, generateJsonLd, generateMetadataTags, generateRobotsTxt, generateSitemap, getAction, getMethod, getPathname, headers, html, isMethod, json, jsonLd, loadMiddleware, loadPlugins, mergeMetadata, middlewares, notFound, parseFormData, parseJson, parseSearchParams, pluginManager, redirect, registerAction, runMiddleware, serverAction, server_default, tailwindPlugin, text, useActionContext, useVelixAction };
2346
- //# sourceMappingURL=chunk-TGNK4MY5.js.map
2347
- //# sourceMappingURL=chunk-TGNK4MY5.js.map
2409
+ //# sourceMappingURL=chunk-DTF3KTLR.js.map
2410
+ //# sourceMappingURL=chunk-DTF3KTLR.js.map