@cfdez11/vex 0.7.0 → 0.8.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.
@@ -0,0 +1,6 @@
1
+ // Barrel file for vex/navigation imports.
2
+ // Components import { useRouteParams } from "vex/navigation" which esbuild
3
+ // rewrites to /_vexjs/services/navigation.js (external). All re-exports go
4
+ // through navigation/index.js so the browser module cache ensures the same
5
+ // runtime instance is shared with the index.js bootstrap.
6
+ export { useRouteParams, useQueryParams, navigate } from "./navigation/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfdez11/vex",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "A vanilla JavaScript meta-framework with file-based routing, SSR/CSR/SSG/ISR and Vue-like reactivity",
5
5
  "type": "module",
6
6
  "main": "./server/index.js",
@@ -46,24 +46,36 @@ const frameworkScripts = [
46
46
  shell = shell.replace("</head>", ` ${frameworkScripts}\n</head>`);
47
47
  await fs.writeFile(path.join(DIST_DIR, "index.html"), shell, "utf-8");
48
48
 
49
- // Step 4: Copy framework client files → dist/_vexjs/
50
- console.log("šŸ“¦ Copying framework client files...");
51
- await fs.cp(CLIENT_DIR, path.join(DIST_DIR, "_vexjs"), { recursive: true });
49
+ // Step 4: Copy static framework assets (favicon.ico, app.webmanifest) → dist/_vexjs/
50
+ // JS runtime files live in .vexjs/services/ (copied in step 5) — no need to
51
+ // copy CLIENT_DIR/services/ separately.
52
+ console.log("šŸ“¦ Copying framework assets...");
53
+ for (const asset of ["favicon.ico", "app.webmanifest"]) {
54
+ try {
55
+ await fs.copyFile(
56
+ path.join(CLIENT_DIR, asset),
57
+ path.join(DIST_DIR, "_vexjs", asset)
58
+ );
59
+ } catch {
60
+ // asset not present — skip
61
+ }
62
+ }
52
63
 
53
- // Step 5: Copy generated component bundles → dist/_vexjs/_components/
54
- console.log("šŸ“¦ Copying component bundles...");
64
+ // Step 5: Copy generated services → dist/_vexjs/services/
65
+ // .vexjs/services/ already contains both framework JS (copied by initializeDirectories)
66
+ // and generated files (_routes.js). One copy covers everything.
67
+ console.log("šŸ“¦ Copying services...");
55
68
  await fs.cp(
56
- path.join(GENERATED_DIR, "_components"),
57
- path.join(DIST_DIR, "_vexjs", "_components"),
69
+ path.join(GENERATED_DIR, "services"),
70
+ path.join(DIST_DIR, "_vexjs", "services"),
58
71
  { recursive: true }
59
72
  );
60
73
 
61
- // Step 6: Copy generated services (includes _routes.js) → dist/_vexjs/services/
62
- // This overwrites the framework-level services dir copy with the generated routes
63
- console.log("šŸ“¦ Copying generated services...");
74
+ // Step 6: Copy generated component bundles → dist/_vexjs/_components/
75
+ console.log("šŸ“¦ Copying component bundles...");
64
76
  await fs.cp(
65
- path.join(GENERATED_DIR, "services"),
66
- path.join(DIST_DIR, "_vexjs", "services"),
77
+ path.join(GENERATED_DIR, "_components"),
78
+ path.join(DIST_DIR, "_vexjs", "_components"),
67
79
  { recursive: true }
68
80
  );
69
81
 
@@ -77,7 +89,7 @@ try {
77
89
  // no user JS files — that's fine
78
90
  }
79
91
 
80
- // Step 8: Copy public/ → dist/ (static assets, CSS)
92
+ // Step 8: Copy public/ → dist/
81
93
  console.log("šŸ“¦ Copying public assets...");
82
94
  const publicDir = path.join(PROJECT_ROOT, "public");
83
95
  try {
@@ -86,7 +98,7 @@ try {
86
98
  // no public/ directory — that's fine
87
99
  }
88
100
 
89
- // Step 9: Copy pre-rendered HTML for SSG routes (revalidate: 'never')
101
+ // Step 9: Copy pre-rendered SSG pages
90
102
  const CACHE_DIR = path.join(GENERATED_DIR, "_cache");
91
103
  const ssgRoutes = serverRoutes.filter(
92
104
  (r) => r.meta.revalidate === "never" || r.meta.revalidate === false
@@ -108,7 +120,7 @@ if (ssgRoutes.length > 0) {
108
120
  }
109
121
  }
110
122
 
111
- // Step 10: Report SSR-only routes that were skipped
123
+ // Step 10: Report SSR-only routes (skipped in static build)
112
124
  const ssrOnlyRoutes = serverRoutes.filter((r) => r.meta.ssr);
113
125
  if (ssrOnlyRoutes.length > 0) {
114
126
  console.warn("\nāš ļø The following routes require a server and were NOT included in the static build:");
package/server/index.js CHANGED
@@ -29,8 +29,6 @@ if (process.env.NODE_ENV === "production") {
29
29
  const app = express();
30
30
 
31
31
  // Serve generated client component bundles at /_vexjs/_components/
32
- // Must be registered before the broader /_vexjs static mount below so that
33
- // .vexjs/_components/ takes priority over anything in CLIENT_DIR/_components/.
34
32
  app.use(
35
33
  "/_vexjs/_components",
36
34
  express.static(path.join(process.cwd(), ".vexjs", "_components"), {
@@ -42,9 +40,9 @@ app.use(
42
40
  })
43
41
  );
44
42
 
45
- // Serve generated services (e.g. _routes.js) at /_vexjs/services/
46
- // Also before the broader /_vexjs mount so the generated _routes.js
47
- // overrides any placeholder that might exist in the framework source.
43
+ // Serve framework runtime JS + generated files (_routes.js) at /_vexjs/services/
44
+ // initializeDirectories() pre-populates this dir with framework files; build()
45
+ // adds generated files (_routes.js). Single source of truth for all /_vexjs/services/*.
48
46
  app.use(
49
47
  "/_vexjs/services",
50
48
  express.static(path.join(process.cwd(), ".vexjs", "services"), {
@@ -56,13 +54,13 @@ app.use(
56
54
  })
57
55
  );
58
56
 
59
- // Serve framework client runtime files at /_vexjs/
60
- // (reactive.js, html.js, hydrate.js, navigation/, etc.)
61
- // User imports like `vex/reactive` are marked external by esbuild and resolved
62
- // here at runtime — a single shared instance per page load.
57
+ // Serve pre-bundled user JS utility files at /_vexjs/user/
58
+ // Registered before the generic /_vexjs mount so requests don't fall through
59
+ // to CLIENT_DIR unnecessarily. esbuild bundles each file with npm packages
60
+ // inlined; vex/*, @/*, and relative user imports stay external (singletons).
63
61
  app.use(
64
- "/_vexjs",
65
- express.static(CLIENT_DIR, {
62
+ "/_vexjs/user",
63
+ express.static(USER_GENERATED_DIR, {
66
64
  setHeaders(res, filePath) {
67
65
  if (filePath.endsWith(".js")) {
68
66
  res.setHeader("Content-Type", "application/javascript");
@@ -71,15 +69,12 @@ app.use(
71
69
  })
72
70
  );
73
71
 
74
-
75
- // Serve pre-bundled user JS utility files at /_vexjs/user/
76
- // These are @/ and relative imports in <script client> blocks. esbuild bundles
77
- // each file with npm packages inlined; vex/*, @/*, and relative user imports
78
- // stay external so every component shares the same singleton module instance
79
- // via the browser's ES module cache.
72
+ // Serve static framework assets (favicon.ico, app.webmanifest) from CLIENT_DIR.
73
+ // Runtime JS files (reactive.js, index.js, etc.) are already in .vexjs/services/
74
+ // via initializeDirectories() and are served by the /_vexjs/services route above.
80
75
  app.use(
81
- "/_vexjs/user",
82
- express.static(USER_GENERATED_DIR, {
76
+ "/_vexjs",
77
+ express.static(CLIENT_DIR, {
83
78
  setHeaders(res, filePath) {
84
79
  if (filePath.endsWith(".js")) {
85
80
  res.setHeader("Content-Type", "application/javascript");
@@ -112,7 +112,6 @@ const GENERATED_DIR = path.join(PROJECT_ROOT, ".vexjs");
112
112
  const CACHE_DIR = path.join(GENERATED_DIR, "_cache");
113
113
  export const CLIENT_COMPONENTS_DIR = path.join(GENERATED_DIR, "_components");
114
114
  export const USER_GENERATED_DIR = path.join(GENERATED_DIR, "user");
115
- const SERVER_UTILS_DIR = path.join(GENERATED_DIR);
116
115
  const ROOT_HTML_USER = path.join(PROJECT_ROOT, "root.html");
117
116
  const ROOT_HTML_DEFAULT = path.join(FRAMEWORK_DIR, "server", "root.html");
118
117
  export const ROOT_HTML_DIR = ROOT_HTML_USER;
@@ -134,14 +133,21 @@ export const ROOT_HTML_DIR = ROOT_HTML_USER;
134
133
  */
135
134
  export async function initializeDirectories() {
136
135
  try {
136
+ const servicesDir = path.join(GENERATED_DIR, "services");
137
137
  await Promise.all([
138
138
  fs.mkdir(GENERATED_DIR, { recursive: true }),
139
139
  fs.mkdir(CACHE_DIR, { recursive: true }),
140
140
  fs.mkdir(CLIENT_COMPONENTS_DIR, { recursive: true }),
141
141
  fs.mkdir(USER_GENERATED_DIR, { recursive: true }),
142
- fs.mkdir(path.join(GENERATED_DIR, "services"), { recursive: true }),
142
+ fs.mkdir(servicesDir, { recursive: true }),
143
143
  ]);
144
144
 
145
+ // Copy framework client runtime files into .vexjs/services/ so they are
146
+ // served by the /_vexjs/services static route alongside generated files
147
+ // like _routes.js. Generated files (prefixed with _) are written later by
148
+ // the build step and overwrite any stale copies here.
149
+ await fs.cp(CLIENT_SERVICES_DIR, servicesDir, { recursive: true });
150
+
145
151
  return true;
146
152
  } catch (err) {
147
153
  console.error("Failed to create cache directory:", err);