@zenithbuild/core 0.6.0 → 0.6.2

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.
@@ -1,6 +1,5 @@
1
1
  import path from 'path'
2
2
  import fs from 'fs'
3
- import os from 'os'
4
3
  import { serve, type ServerWebSocket } from 'bun'
5
4
  import { requireProject } from '../utils/project'
6
5
  import * as logger from '../utils/logger'
@@ -40,21 +39,23 @@ async function bundlePageScript(script: string, projectRoot: string): Promise<st
40
39
  return script
41
40
  }
42
41
 
43
- // Create a temporary file for bundling
44
- const tempDir = os.tmpdir()
45
- const tempFile = path.join(tempDir, `zenith-bundle-${Date.now()}.js`)
42
+ // Write temp file in PROJECT directory so Bun can find node_modules
43
+ const tempDir = path.join(projectRoot, '.zenith-cache')
44
+ if (!fs.existsSync(tempDir)) {
45
+ fs.mkdirSync(tempDir, { recursive: true })
46
+ }
47
+ const tempFile = path.join(tempDir, `bundle-${Date.now()}.js`)
46
48
 
47
49
  try {
48
50
  // Write script to temp file
49
51
  fs.writeFileSync(tempFile, script, 'utf-8')
50
52
 
51
- // Use Bun.build to bundle with npm resolution
53
+ // Use Bun.build to bundle with npm resolution from project's node_modules
52
54
  const result = await Bun.build({
53
55
  entrypoints: [tempFile],
54
56
  target: 'browser',
55
57
  format: 'esm',
56
58
  minify: false,
57
- // Resolve modules from the project's node_modules
58
59
  external: [], // Bundle everything
59
60
  })
60
61
 
@@ -18,7 +18,7 @@ import {
18
18
  discoverPages,
19
19
  generateRouteDefinition,
20
20
  routePathToRegex
21
- } from "../router/manifest"
21
+ } from "@zenithbuild/router/manifest"
22
22
 
23
23
  interface CompiledPage {
24
24
  routePath: string
@@ -16,7 +16,7 @@ import path from "path"
16
16
  import { compileZenSource } from "./index"
17
17
  import { discoverLayouts } from "./discovery/layouts"
18
18
  import { processLayout } from "./transform/layoutProcessor"
19
- import { discoverPages, generateRouteDefinition } from "../router/manifest"
19
+ import { discoverPages, generateRouteDefinition } from "@zenithbuild/router/manifest"
20
20
  import { analyzePageSource, getAnalysisSummary, getBuildOutputType, type PageAnalysis } from "./build-analyzer"
21
21
  import { generateBundleJS } from "../runtime/bundle-generator"
22
22
  import { loadContent } from "../cli/utils/content"
package/dist/cli.js CHANGED
@@ -18,6 +18,7 @@
18
18
  #!/usr/bin/env bun
19
19
  #!/usr/bin/env bun
20
20
  #!/usr/bin/env bun
21
+ #!/usr/bin/env bun
21
22
  // @bun
22
23
  var __create = Object.create;
23
24
  var __getProtoOf = Object.getPrototypeOf;
package/dist/zen-build.js CHANGED
@@ -9285,7 +9285,6 @@ import process2 from "process";
9285
9285
  // cli/commands/dev.ts
9286
9286
  import path8 from "path";
9287
9287
  import fs8 from "fs";
9288
- import os from "os";
9289
9288
  var {serve } = globalThis.Bun;
9290
9289
 
9291
9290
  // cli/utils/project.ts
@@ -19671,8 +19670,11 @@ async function bundlePageScript(script, projectRoot) {
19671
19670
  if (!script.includes("import ")) {
19672
19671
  return script;
19673
19672
  }
19674
- const tempDir = os.tmpdir();
19675
- const tempFile = path8.join(tempDir, `zenith-bundle-${Date.now()}.js`);
19673
+ const tempDir = path8.join(projectRoot, ".zenith-cache");
19674
+ if (!fs8.existsSync(tempDir)) {
19675
+ fs8.mkdirSync(tempDir, { recursive: true });
19676
+ }
19677
+ const tempFile = path8.join(tempDir, `bundle-${Date.now()}.js`);
19676
19678
  try {
19677
19679
  fs8.writeFileSync(tempFile, script, "utf-8");
19678
19680
  const result = await Bun.build({
package/dist/zen-dev.js CHANGED
@@ -9285,7 +9285,6 @@ import process2 from "process";
9285
9285
  // cli/commands/dev.ts
9286
9286
  import path8 from "path";
9287
9287
  import fs8 from "fs";
9288
- import os from "os";
9289
9288
  var {serve } = globalThis.Bun;
9290
9289
 
9291
9290
  // cli/utils/project.ts
@@ -19671,8 +19670,11 @@ async function bundlePageScript(script, projectRoot) {
19671
19670
  if (!script.includes("import ")) {
19672
19671
  return script;
19673
19672
  }
19674
- const tempDir = os.tmpdir();
19675
- const tempFile = path8.join(tempDir, `zenith-bundle-${Date.now()}.js`);
19673
+ const tempDir = path8.join(projectRoot, ".zenith-cache");
19674
+ if (!fs8.existsSync(tempDir)) {
19675
+ fs8.mkdirSync(tempDir, { recursive: true });
19676
+ }
19677
+ const tempFile = path8.join(tempDir, `bundle-${Date.now()}.js`);
19676
19678
  try {
19677
19679
  fs8.writeFileSync(tempFile, script, "utf-8");
19678
19680
  const result = await Bun.build({
@@ -9285,7 +9285,6 @@ import process2 from "process";
9285
9285
  // cli/commands/dev.ts
9286
9286
  import path8 from "path";
9287
9287
  import fs8 from "fs";
9288
- import os from "os";
9289
9288
  var {serve } = globalThis.Bun;
9290
9289
 
9291
9290
  // cli/utils/project.ts
@@ -19671,8 +19670,11 @@ async function bundlePageScript(script, projectRoot) {
19671
19670
  if (!script.includes("import ")) {
19672
19671
  return script;
19673
19672
  }
19674
- const tempDir = os.tmpdir();
19675
- const tempFile = path8.join(tempDir, `zenith-bundle-${Date.now()}.js`);
19673
+ const tempDir = path8.join(projectRoot, ".zenith-cache");
19674
+ if (!fs8.existsSync(tempDir)) {
19675
+ fs8.mkdirSync(tempDir, { recursive: true });
19676
+ }
19677
+ const tempFile = path8.join(tempDir, `bundle-${Date.now()}.js`);
19676
19678
  try {
19677
19679
  fs8.writeFileSync(tempFile, script, "utf-8");
19678
19680
  const result = await Bun.build({
package/dist/zenith.js CHANGED
@@ -9285,7 +9285,6 @@ import process2 from "process";
9285
9285
  // cli/commands/dev.ts
9286
9286
  import path8 from "path";
9287
9287
  import fs8 from "fs";
9288
- import os from "os";
9289
9288
  var {serve } = globalThis.Bun;
9290
9289
 
9291
9290
  // cli/utils/project.ts
@@ -19671,8 +19670,11 @@ async function bundlePageScript(script, projectRoot) {
19671
19670
  if (!script.includes("import ")) {
19672
19671
  return script;
19673
19672
  }
19674
- const tempDir = os.tmpdir();
19675
- const tempFile = path8.join(tempDir, `zenith-bundle-${Date.now()}.js`);
19673
+ const tempDir = path8.join(projectRoot, ".zenith-cache");
19674
+ if (!fs8.existsSync(tempDir)) {
19675
+ fs8.mkdirSync(tempDir, { recursive: true });
19676
+ }
19677
+ const tempFile = path8.join(tempDir, `bundle-${Date.now()}.js`);
19676
19678
  try {
19677
19679
  fs8.writeFileSync(tempFile, script, "utf-8");
19678
19680
  const result = await Bun.build({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenithbuild/core",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Core library for the Zenith framework",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -59,6 +59,7 @@
59
59
  "typescript": "^5"
60
60
  },
61
61
  "dependencies": {
62
+ "@zenithbuild/router": "latest",
62
63
  "@types/acorn": "^6.0.4",
63
64
  "@types/marked": "^6.0.0",
64
65
  "@types/parse5": "^7.0.0",
package/router/index.ts CHANGED
@@ -1,8 +1,12 @@
1
1
  /**
2
2
  * Zenith Router
3
3
  *
4
- * File-based SPA router for Zenith framework.
5
- * Includes routing, navigation, and ZenLink components.
4
+ * This module re-exports from @zenithbuild/router package.
5
+ *
6
+ * The router has been extracted to its own package for:
7
+ * - Independent versioning
8
+ * - Better separation of concerns
9
+ * - Easier maintenance
6
10
  *
7
11
  * @example
8
12
  * ```ts
@@ -16,61 +20,9 @@
16
20
  * console.log('On blog section')
17
21
  * }
18
22
  * ```
23
+ *
24
+ * @deprecated Import directly from '@zenithbuild/router' for new projects
19
25
  */
20
26
 
21
- // Core router types and utilities
22
- export * from "./types"
23
- export * from "./manifest"
24
-
25
- // Router runtime (core router implementation)
26
- // These are the primary exports for router functionality
27
- export {
28
- initRouter,
29
- resolveRoute,
30
- navigate,
31
- getRoute,
32
- onRouteChange,
33
- beforeEach,
34
- afterEach,
35
- isActive,
36
- prefetch,
37
- isPrefetched
38
- } from "./runtime"
39
-
40
- // Navigation utilities (additional helpers and zen* prefixed exports)
41
- // Note: Some functions like navigate, isActive, prefetch are also in runtime
42
- // We export runtime's versions above, and navigation's unique functions here
43
- export {
44
- // Navigation API (zen* prefixed names)
45
- zenNavigate,
46
- zenBack,
47
- zenForward,
48
- zenGo,
49
- zenIsActive,
50
- zenPrefetch,
51
- zenIsPrefetched,
52
- zenGetRoute,
53
- zenGetParam,
54
- zenGetQuery,
55
- createZenLink,
56
- zenLink,
57
- // Additional navigation utilities (not in runtime)
58
- back,
59
- forward,
60
- go,
61
- getParam,
62
- getQuery,
63
- isExternalUrl,
64
- shouldUseSPANavigation,
65
- normalizePath,
66
- setGlobalTransition,
67
- getGlobalTransition,
68
- createTransitionContext
69
- } from "./navigation/index"
70
-
71
- // Navigation-specific types
72
- export type {
73
- ZenLinkProps,
74
- TransitionContext,
75
- TransitionHandler
76
- } from "./navigation/index"
27
+ // Re-export everything from @zenithbuild/router
28
+ export * from "@zenithbuild/router"
@@ -876,6 +876,310 @@ export function generateBundleJS(): string {
876
876
  global.processRawSections = processRawSections;
877
877
  global.slugify = slugify;
878
878
 
879
+ // ============================================
880
+ // SPA Router Runtime
881
+ // ============================================
882
+
883
+ (function() {
884
+ 'use strict';
885
+
886
+ // Current route state
887
+ var currentRoute = {
888
+ path: '/',
889
+ params: {},
890
+ query: {}
891
+ };
892
+
893
+ // Route listeners
894
+ var routeListeners = new Set();
895
+
896
+ // Router outlet element
897
+ var routerOutlet = null;
898
+
899
+ // Page modules registry
900
+ var pageModules = {};
901
+
902
+ // Route manifest
903
+ var routeManifest = [];
904
+
905
+ /**
906
+ * Parse query string
907
+ */
908
+ function parseQueryString(search) {
909
+ var query = {};
910
+ if (!search || search === '?') return query;
911
+ var params = new URLSearchParams(search);
912
+ params.forEach(function(value, key) { query[key] = value; });
913
+ return query;
914
+ }
915
+
916
+ /**
917
+ * Resolve route from pathname
918
+ */
919
+ function resolveRoute(pathname) {
920
+ var normalizedPath = pathname === '' ? '/' : pathname;
921
+
922
+ for (var i = 0; i < routeManifest.length; i++) {
923
+ var route = routeManifest[i];
924
+ var match = route.regex.exec(normalizedPath);
925
+ if (match) {
926
+ var params = {};
927
+ for (var j = 0; j < route.paramNames.length; j++) {
928
+ var paramValue = match[j + 1];
929
+ if (paramValue !== undefined) {
930
+ params[route.paramNames[j]] = decodeURIComponent(paramValue);
931
+ }
932
+ }
933
+ return { record: route, params: params };
934
+ }
935
+ }
936
+ return null;
937
+ }
938
+
939
+ /**
940
+ * Clean up previous page
941
+ */
942
+ function cleanupPreviousPage() {
943
+ // Trigger unmount lifecycle hooks
944
+ if (global.__zenith && global.__zenith.triggerUnmount) {
945
+ global.__zenith.triggerUnmount();
946
+ }
947
+
948
+ // Remove previous page styles
949
+ var prevStyles = document.querySelectorAll('style[data-zen-page-style]');
950
+ prevStyles.forEach(function(s) { s.remove(); });
951
+
952
+ // Clean up window properties
953
+ if (global.__zenith_cleanup) {
954
+ global.__zenith_cleanup.forEach(function(key) {
955
+ try { delete global[key]; } catch(e) {}
956
+ });
957
+ }
958
+ global.__zenith_cleanup = [];
959
+ }
960
+
961
+ /**
962
+ * Inject styles
963
+ */
964
+ function injectStyles(styles) {
965
+ styles.forEach(function(content, i) {
966
+ var style = document.createElement('style');
967
+ style.setAttribute('data-zen-page-style', String(i));
968
+ style.textContent = content;
969
+ document.head.appendChild(style);
970
+ });
971
+ }
972
+
973
+ /**
974
+ * Execute scripts
975
+ */
976
+ function executeScripts(scripts) {
977
+ scripts.forEach(function(content) {
978
+ try {
979
+ var fn = new Function(content);
980
+ fn();
981
+ } catch (e) {
982
+ console.error('[Zenith Router] Script error:', e);
983
+ }
984
+ });
985
+ }
986
+
987
+ /**
988
+ * Render page
989
+ */
990
+ function renderPage(pageModule) {
991
+ if (!routerOutlet) {
992
+ console.warn('[Zenith Router] No router outlet');
993
+ return;
994
+ }
995
+
996
+ cleanupPreviousPage();
997
+ routerOutlet.innerHTML = pageModule.html;
998
+ injectStyles(pageModule.styles);
999
+ executeScripts(pageModule.scripts);
1000
+
1001
+ // Trigger mount lifecycle hooks after scripts are executed
1002
+ if (global.__zenith && global.__zenith.triggerMount) {
1003
+ global.__zenith.triggerMount();
1004
+ }
1005
+ }
1006
+
1007
+ /**
1008
+ * Notify listeners
1009
+ */
1010
+ function notifyListeners(route, prevRoute) {
1011
+ routeListeners.forEach(function(listener) {
1012
+ try { listener(route, prevRoute); } catch(e) {}
1013
+ });
1014
+ }
1015
+
1016
+ /**
1017
+ * Resolve and render
1018
+ */
1019
+ function resolveAndRender(path, query, updateHistory, replace) {
1020
+ replace = replace || false;
1021
+ var prevRoute = Object.assign({}, currentRoute);
1022
+ var resolved = resolveRoute(path);
1023
+
1024
+ if (resolved) {
1025
+ currentRoute = {
1026
+ path: path,
1027
+ params: resolved.params,
1028
+ query: query,
1029
+ matched: resolved.record
1030
+ };
1031
+
1032
+ var pageModule = pageModules[resolved.record.path];
1033
+ if (pageModule) {
1034
+ renderPage(pageModule);
1035
+ }
1036
+ } else {
1037
+ currentRoute = { path: path, params: {}, query: query, matched: undefined };
1038
+ console.warn('[Zenith Router] No route matched:', path);
1039
+
1040
+ // Render 404 if available
1041
+ if (routerOutlet) {
1042
+ routerOutlet.innerHTML = '<div style="padding: 2rem; text-align: center;"><h1>404</h1><p>Page not found</p></div>';
1043
+ }
1044
+ }
1045
+
1046
+ if (updateHistory) {
1047
+ var url = path + (Object.keys(query).length ? '?' + new URLSearchParams(query) : '');
1048
+ if (replace) {
1049
+ history.replaceState(null, '', url);
1050
+ } else {
1051
+ history.pushState(null, '', url);
1052
+ }
1053
+ }
1054
+
1055
+ notifyListeners(currentRoute, prevRoute);
1056
+ global.__zenith_route = currentRoute;
1057
+ }
1058
+
1059
+ /**
1060
+ * Handle popstate
1061
+ */
1062
+ function handlePopState() {
1063
+ resolveAndRender(
1064
+ location.pathname,
1065
+ parseQueryString(location.search),
1066
+ false,
1067
+ false
1068
+ );
1069
+ }
1070
+
1071
+ /**
1072
+ * Navigate (public API)
1073
+ */
1074
+ function navigate(to, options) {
1075
+ options = options || {};
1076
+ var path, query = {};
1077
+
1078
+ if (to.includes('?')) {
1079
+ var parts = to.split('?');
1080
+ path = parts[0];
1081
+ query = parseQueryString('?' + parts[1]);
1082
+ } else {
1083
+ path = to;
1084
+ }
1085
+
1086
+ if (!path.startsWith('/')) {
1087
+ var currentDir = currentRoute.path.split('/').slice(0, -1).join('/');
1088
+ path = currentDir + '/' + path;
1089
+ }
1090
+
1091
+ var normalizedPath = path === '' ? '/' : path;
1092
+ var currentPath = currentRoute.path === '' ? '/' : currentRoute.path;
1093
+ var isSamePath = normalizedPath === currentPath;
1094
+
1095
+ if (isSamePath && JSON.stringify(query) === JSON.stringify(currentRoute.query)) {
1096
+ return;
1097
+ }
1098
+
1099
+ resolveAndRender(path, query, true, options.replace || false);
1100
+ }
1101
+
1102
+ /**
1103
+ * Get current route
1104
+ */
1105
+ function getRoute() {
1106
+ return Object.assign({}, currentRoute);
1107
+ }
1108
+
1109
+ /**
1110
+ * Subscribe to route changes
1111
+ */
1112
+ function onRouteChange(listener) {
1113
+ routeListeners.add(listener);
1114
+ return function() { routeListeners.delete(listener); };
1115
+ }
1116
+
1117
+ /**
1118
+ * Check if path is active
1119
+ */
1120
+ function isActive(path, exact) {
1121
+ if (exact) return currentRoute.path === path;
1122
+ return currentRoute.path.startsWith(path);
1123
+ }
1124
+
1125
+ /**
1126
+ * Prefetch a route
1127
+ */
1128
+ var prefetchedRoutes = new Set();
1129
+ function prefetch(path) {
1130
+ var normalizedPath = path === '' ? '/' : path;
1131
+
1132
+ if (prefetchedRoutes.has(normalizedPath)) {
1133
+ return Promise.resolve();
1134
+ }
1135
+ prefetchedRoutes.add(normalizedPath);
1136
+
1137
+ var resolved = resolveRoute(normalizedPath);
1138
+ if (!resolved) {
1139
+ return Promise.resolve();
1140
+ }
1141
+
1142
+ // In SPA build, all modules are already loaded
1143
+ return Promise.resolve();
1144
+ }
1145
+
1146
+ /**
1147
+ * Initialize router
1148
+ */
1149
+ function initRouter(manifest, modules, outlet) {
1150
+ routeManifest = manifest;
1151
+ Object.assign(pageModules, modules);
1152
+
1153
+ if (outlet) {
1154
+ routerOutlet = typeof outlet === 'string'
1155
+ ? document.querySelector(outlet)
1156
+ : outlet;
1157
+ }
1158
+
1159
+ window.addEventListener('popstate', handlePopState);
1160
+
1161
+ // Initial route resolution
1162
+ resolveAndRender(
1163
+ location.pathname,
1164
+ parseQueryString(location.search),
1165
+ false
1166
+ );
1167
+ }
1168
+
1169
+ // Expose router API globally
1170
+ global.__zenith_router = {
1171
+ navigate: navigate,
1172
+ getRoute: getRoute,
1173
+ onRouteChange: onRouteChange,
1174
+ isActive: isActive,
1175
+ prefetch: prefetch,
1176
+ initRouter: initRouter
1177
+ };
1178
+
1179
+ // Also expose navigate directly for convenience
1180
+ global.navigate = navigate;
1181
+ })();
1182
+
879
1183
  // ============================================
880
1184
  // HMR Client (Development Only)
881
1185
  // ============================================