@zenithbuild/bundler 1.3.17 → 1.3.19

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 (51) hide show
  1. package/dev-server.js +101 -7
  2. package/dist/build-analyzer.d.ts +45 -0
  3. package/dist/build-analyzer.d.ts.map +1 -0
  4. package/dist/build-analyzer.js +88 -0
  5. package/dist/build-analyzer.js.map +1 -0
  6. package/dist/bundle-generator.d.ts +19 -0
  7. package/dist/bundle-generator.d.ts.map +1 -0
  8. package/dist/bundle-generator.js +848 -0
  9. package/dist/bundle-generator.js.map +1 -0
  10. package/dist/bundler.d.ts +32 -0
  11. package/dist/bundler.d.ts.map +1 -0
  12. package/dist/bundler.js +87 -0
  13. package/dist/bundler.js.map +1 -0
  14. package/dist/css.d.ts +60 -0
  15. package/dist/css.d.ts.map +1 -0
  16. package/dist/css.js +229 -0
  17. package/dist/css.js.map +1 -0
  18. package/dist/discovery/componentDiscovery.d.ts +42 -0
  19. package/dist/discovery/componentDiscovery.d.ts.map +1 -0
  20. package/dist/discovery/componentDiscovery.js +67 -0
  21. package/dist/discovery/componentDiscovery.js.map +1 -0
  22. package/dist/discovery/layouts.d.ts +15 -0
  23. package/dist/discovery/layouts.d.ts.map +1 -0
  24. package/dist/discovery/layouts.js +37 -0
  25. package/dist/discovery/layouts.js.map +1 -0
  26. package/dist/generateFinalBundle.d.ts +25 -0
  27. package/dist/generateFinalBundle.d.ts.map +1 -0
  28. package/dist/generateFinalBundle.js +69 -0
  29. package/dist/generateFinalBundle.js.map +1 -0
  30. package/dist/index.d.ts +12 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/runtime-generator.d.ts +5 -0
  34. package/dist/runtime-generator.d.ts.map +1 -0
  35. package/dist/runtime-generator.js +21 -0
  36. package/dist/runtime-generator.js.map +1 -0
  37. package/dist/spa-build.d.ts +27 -0
  38. package/dist/spa-build.d.ts.map +1 -0
  39. package/dist/spa-build.js +862 -0
  40. package/dist/spa-build.js.map +1 -0
  41. package/dist/ssg-build.d.ts +32 -0
  42. package/dist/ssg-build.d.ts.map +1 -0
  43. package/dist/ssg-build.js +441 -0
  44. package/dist/ssg-build.js.map +1 -0
  45. package/dist/types.d.ts +6 -0
  46. package/dist/types.d.ts.map +1 -0
  47. package/dist/types.js +2 -0
  48. package/dist/types.js.map +1 -0
  49. package/package.json +3 -2
  50. package/src/bundle-generator.ts +57 -47
  51. package/src/ssg-build.ts +17 -4
package/dev-server.js CHANGED
@@ -14,15 +14,55 @@ const port = 3000;
14
14
  const start = async (projectRoot = process.env.PROJECT_ROOT || path.resolve(__dirname, '..')) => {
15
15
  console.log(`[DevServer] Starting Zenith for: ${projectRoot}`);
16
16
 
17
+ // Dynamic import of JS-based build logic (since dist/index.js is ESM)
18
+ const { compileCssAsync, generateBundleJS, resolveGlobalsCss } = await import('./dist/index.js');
19
+
17
20
  let controller;
18
21
  try {
19
22
  controller = new ZenithDevController(projectRoot);
20
23
  } catch (e) {
21
- console.error("Failed to initialize ZenithDevController:", e);
24
+ console.error("Failed to initialize ZenithDevController:Native controller access is opaque", e);
22
25
  console.error("Ensure you have built the native module: 'napi build --platform'");
23
26
  process.exit(1);
24
27
  }
25
28
 
29
+ // Asset Cache
30
+ const assets = {
31
+ css: '',
32
+ bundle: '',
33
+ cssPath: null
34
+ };
35
+
36
+ // Helper: Rebuild Assets (JS Logic)
37
+ async function rebuildAssets() {
38
+ console.log('[DevServer] Rebuilding JS assets...');
39
+
40
+ // 1. Build CSS
41
+ const globalsCss = resolveGlobalsCss(projectRoot);
42
+ if (globalsCss) {
43
+ const res = await compileCssAsync({
44
+ input: globalsCss,
45
+ output: ':memory:',
46
+ minify: false
47
+ });
48
+ if (res.success) {
49
+ assets.css = res.css;
50
+ console.log('[DevServer] CSS Compiled');
51
+ } else {
52
+ console.error('[DevServer] CSS Compile Failed:', res.error);
53
+ }
54
+ }
55
+
56
+ // 2. Build Bundle
57
+ // optimizing: reusing previous bundle if only CSS changed? No, fast enough.
58
+ // We pass empty pluginData for now as we can't easily extract it from native controller.
59
+ assets.bundle = generateBundleJS({});
60
+ console.log('[DevServer] Bundle Generated');
61
+ }
62
+
63
+ // Initial Build
64
+ await rebuildAssets();
65
+
26
66
  // Create HTTP and WS Server
27
67
  const server = http.createServer(app);
28
68
  const wss = new WebSocketServer({ server });
@@ -40,7 +80,7 @@ const start = async (projectRoot = process.env.PROJECT_ROOT || path.resolve(__di
40
80
  });
41
81
  }
42
82
 
43
- // Watcher Integration (Tactical Fix)
83
+ // Watcher Integration
44
84
  const watchPath = path.join(projectRoot, 'src/**/*.zen');
45
85
  console.log(`[Watcher] Watching ${watchPath}`);
46
86
  const watcher = chokidar.watch(watchPath, {
@@ -53,9 +93,15 @@ const start = async (projectRoot = process.env.PROJECT_ROOT || path.resolve(__di
53
93
  // 1. Tell Rust to re-compile (updates the AssetStore in RAM)
54
94
  console.time('Rebuild');
55
95
  await controller.rebuild();
96
+
97
+ // 2. Rebuild JS assets (CSS/Bundle)
98
+ if (filePath.endsWith('.css') || filePath.endsWith('.zen') || filePath.endsWith('.ts')) {
99
+ await rebuildAssets();
100
+ }
101
+
56
102
  console.timeEnd('Rebuild');
57
103
 
58
- // 2. Tell the Browser to fetch the new assets
104
+ // 3. Tell the Browser to fetch the new assets
59
105
  notifyHMR();
60
106
  } catch (e) {
61
107
  console.error("Rebuild failed:", e);
@@ -64,10 +110,58 @@ const start = async (projectRoot = process.env.PROJECT_ROOT || path.resolve(__di
64
110
 
65
111
  // Serve Assets
66
112
  app.use(async (req, res, next) => {
67
- // 1. Try to serve from memory store
113
+ // Intercept Asset Requests (that Native Controller fails on)
114
+ if (req.path === '/assets/styles.css') {
115
+ res.setHeader('Content-Type', 'text/css');
116
+ return res.send(assets.css);
117
+ }
118
+ if (req.path === '/assets/bundle.js') {
119
+ res.setHeader('Content-Type', 'application/javascript');
120
+ return res.send(assets.bundle);
121
+ }
122
+
123
+ // 1. Try to serve from native memory store (HTML mostly)
68
124
  const asset = controller.getAsset(req.path);
69
125
 
70
126
  if (asset) {
127
+ let content = asset;
128
+
129
+ // Inject Tags into HTML
130
+ if (req.path === '/' || req.path.endsWith('.html')) {
131
+ let html = content.toString();
132
+ const cssTag = `<link rel="stylesheet" href="/assets/styles.css">`;
133
+ const jsTag = `<script type="module" src="/assets/bundle.js"></script>`;
134
+
135
+ // HMR Script
136
+ const hmrScript = `
137
+ <script>
138
+ const ws = new WebSocket('ws://' + location.host);
139
+ ws.onmessage = (event) => {
140
+ const msg = JSON.parse(event.data);
141
+ if (msg.type === 'update') {
142
+ console.log('[HMR] Update received. Reloading...');
143
+ location.reload();
144
+ }
145
+ };
146
+ ws.onopen = () => console.log("[Zenith] HMR Connected");
147
+ </script>`;
148
+
149
+ if (html.includes("</head>")) {
150
+ html = html.replace("</head>", `${cssTag}${hmrScript}</head>`);
151
+ } else {
152
+ html = `${cssTag}${hmrScript}${html}`;
153
+ }
154
+
155
+ if (html.includes("</body>")) {
156
+ html = html.replace("</body>", `${jsTag}</body>`);
157
+ } else {
158
+ html = `${html}${jsTag}`;
159
+ }
160
+
161
+ res.setHeader('Content-Type', 'text/html');
162
+ return res.send(html);
163
+ }
164
+
71
165
  if (req.path.endsWith('.js')) {
72
166
  res.setHeader('Content-Type', 'application/javascript');
73
167
  } else if (req.path.endsWith('.css')) {
@@ -76,15 +170,15 @@ const start = async (projectRoot = process.env.PROJECT_ROOT || path.resolve(__di
76
170
  return res.send(asset);
77
171
  }
78
172
 
79
- // 2. SPA / HTML Fallback
173
+ // 2. Fallback HTML (if native returns nothing for /)
80
174
  if (req.path === '/' || !path.extname(req.path)) {
81
175
  res.send(`
82
176
  <!DOCTYPE html>
83
177
  <html>
84
178
  <head>
85
179
  <title>Zenith Dev</title>
86
- <script type="module" src="/index.js"></script>
87
- <link rel="stylesheet" href="/zenith.css">
180
+ <link rel="stylesheet" href="/assets/styles.css">
181
+ <script type="module" src="/assets/bundle.js"></script>
88
182
  <script>
89
183
  // HMR Client
90
184
  const ws = new WebSocket('ws://' + location.host);
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Zenith Build Analyzer
3
+ *
4
+ * Analyzes .zen page source to determine build strategy:
5
+ * - Static: Pure HTML+CSS, no JS needed
6
+ * - Hydration: Has state/events/hooks, needs page-specific JS
7
+ * - SSR: Uses useFetchServer, needs server rendering
8
+ * - SPA: Uses ZenLink with passHref, needs client router
9
+ */
10
+ export interface PageAnalysis {
11
+ /** Page has state declarations that need hydration */
12
+ hasState: boolean;
13
+ /** Page has event handlers (onclick, etc.) */
14
+ hasEventHandlers: boolean;
15
+ /** Page uses lifecycle hooks (zenOnMount, zenOnUnmount) */
16
+ hasLifecycleHooks: boolean;
17
+ /** Page uses useFetchServer (requires SSR) */
18
+ usesServerFetch: boolean;
19
+ /** Page uses useFetchClient (client-side data) */
20
+ usesClientFetch: boolean;
21
+ /** Page uses ZenLink with passHref (SPA navigation) */
22
+ usesZenLink: boolean;
23
+ /** Page uses reactive expressions in templates */
24
+ hasReactiveExpressions: boolean;
25
+ /** Computed: page needs any JavaScript */
26
+ needsHydration: boolean;
27
+ /** Computed: page is purely static (no JS) */
28
+ isStatic: boolean;
29
+ /** Computed: page needs SSR */
30
+ needsSSR: boolean;
31
+ }
32
+ /**
33
+ * Analyze a .zen page source to determine build requirements
34
+ */
35
+ export declare function analyzePageSource(source: string): PageAnalysis;
36
+ /**
37
+ * Get a human-readable summary of the page analysis
38
+ */
39
+ export declare function getAnalysisSummary(analysis: PageAnalysis): string;
40
+ /**
41
+ * Determine build output type for a page
42
+ */
43
+ export type BuildOutputType = 'static' | 'hydrated' | 'ssr';
44
+ export declare function getBuildOutputType(analysis: PageAnalysis): BuildOutputType;
45
+ //# sourceMappingURL=build-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-analyzer.d.ts","sourceRoot":"","sources":["../src/build-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,YAAY;IACzB,sDAAsD;IACtD,QAAQ,EAAE,OAAO,CAAA;IACjB,8CAA8C;IAC9C,gBAAgB,EAAE,OAAO,CAAA;IACzB,2DAA2D;IAC3D,iBAAiB,EAAE,OAAO,CAAA;IAC1B,8CAA8C;IAC9C,eAAe,EAAE,OAAO,CAAA;IACxB,kDAAkD;IAClD,eAAe,EAAE,OAAO,CAAA;IACxB,uDAAuD;IACvD,WAAW,EAAE,OAAO,CAAA;IACpB,kDAAkD;IAClD,sBAAsB,EAAE,OAAO,CAAA;IAE/B,0CAA0C;IAC1C,cAAc,EAAE,OAAO,CAAA;IACvB,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAA;IACjB,+BAA+B;IAC/B,QAAQ,EAAE,OAAO,CAAA;CACpB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAmD9D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAiBjE;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,UAAU,GAAG,KAAK,CAAA;AAE3D,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,eAAe,CAI1E"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Zenith Build Analyzer
3
+ *
4
+ * Analyzes .zen page source to determine build strategy:
5
+ * - Static: Pure HTML+CSS, no JS needed
6
+ * - Hydration: Has state/events/hooks, needs page-specific JS
7
+ * - SSR: Uses useFetchServer, needs server rendering
8
+ * - SPA: Uses ZenLink with passHref, needs client router
9
+ */
10
+ /**
11
+ * Analyze a .zen page source to determine build requirements
12
+ */
13
+ export function analyzePageSource(source) {
14
+ // Extract script content for analysis
15
+ const scriptMatch = source.match(/<script[^>]*>([\s\S]*?)<\/script>/i);
16
+ const scriptContent = scriptMatch?.[1] || '';
17
+ // Extract template content (everything outside script/style)
18
+ const templateContent = source
19
+ .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
20
+ .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '');
21
+ // Check for state declarations: "state varName = ..."
22
+ const hasState = /\bstate\s+\w+\s*=/.test(scriptContent);
23
+ // Check for event handlers in template
24
+ const hasEventHandlers = /\bon(click|change|input|submit|focus|blur|keydown|keyup|keypress|mousedown|mouseup|mouseover|mouseout|mouseenter|mouseleave|load)\s*=\s*["'{]/.test(templateContent);
25
+ // Check for lifecycle hooks
26
+ const hasLifecycleHooks = /\bzen(OnMount|OnUnmount)\s*\(/.test(scriptContent);
27
+ // Check for server fetch
28
+ const usesServerFetch = /\buseFetchServer\s*\(/.test(scriptContent);
29
+ // Check for client fetch
30
+ const usesClientFetch = /\buseFetchClient\s*\(/.test(scriptContent);
31
+ // Check for ZenLink with passHref
32
+ const usesZenLink = /<ZenLink[^>]*passHref[^>]*>/.test(templateContent);
33
+ // Check for reactive expressions in template: {expression}
34
+ // Must be actual expressions, not just static text
35
+ // Exclude attribute values like href="/path"
36
+ const hasReactiveExpressions = /{[^{}]+}/.test(templateContent);
37
+ // Compute derived properties
38
+ const needsHydration = hasState || hasEventHandlers || hasLifecycleHooks ||
39
+ usesClientFetch || hasReactiveExpressions;
40
+ const isStatic = !needsHydration && !usesServerFetch;
41
+ const needsSSR = usesServerFetch;
42
+ return {
43
+ hasState,
44
+ hasEventHandlers,
45
+ hasLifecycleHooks,
46
+ usesServerFetch,
47
+ usesClientFetch,
48
+ usesZenLink,
49
+ hasReactiveExpressions,
50
+ needsHydration,
51
+ isStatic,
52
+ needsSSR
53
+ };
54
+ }
55
+ /**
56
+ * Get a human-readable summary of the page analysis
57
+ */
58
+ export function getAnalysisSummary(analysis) {
59
+ const flags = [];
60
+ if (analysis.isStatic) {
61
+ flags.push('STATIC (no JS)');
62
+ }
63
+ else {
64
+ if (analysis.hasState)
65
+ flags.push('state');
66
+ if (analysis.hasEventHandlers)
67
+ flags.push('events');
68
+ if (analysis.hasLifecycleHooks)
69
+ flags.push('lifecycle');
70
+ if (analysis.hasReactiveExpressions)
71
+ flags.push('reactive');
72
+ if (analysis.usesClientFetch)
73
+ flags.push('clientFetch');
74
+ }
75
+ if (analysis.needsSSR)
76
+ flags.push('SSR');
77
+ if (analysis.usesZenLink)
78
+ flags.push('SPA');
79
+ return flags.length > 0 ? flags.join(', ') : 'minimal';
80
+ }
81
+ export function getBuildOutputType(analysis) {
82
+ if (analysis.needsSSR)
83
+ return 'ssr';
84
+ if (analysis.needsHydration)
85
+ return 'hydrated';
86
+ return 'static';
87
+ }
88
+ //# sourceMappingURL=build-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-analyzer.js","sourceRoot":"","sources":["../src/build-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Zenith Bundle Generator
3
+ *
4
+ * Generates the shared client runtime bundle that gets served as:
5
+ * - /assets/bundle.js in production
6
+ * - /runtime.js in development
7
+ *
8
+ * This is a cacheable, versioned file that contains:
9
+ * - Reactivity primitives (zenSignal, zenState, zenEffect, etc.)
10
+ * - Lifecycle hooks (zenOnMount, zenOnUnmount)
11
+ * - Hydration functions (zenithHydrate)
12
+ * - Event binding utilities
13
+ */
14
+ /**
15
+ * Generate the complete client runtime bundle
16
+ * This is served as an external JS file, not inlined
17
+ */
18
+ export declare function generateBundleJS(pluginData?: Record<string, any>): string;
19
+ //# sourceMappingURL=bundle-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle-generator.d.ts","sourceRoot":"","sources":["../src/bundle-generator.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AAEH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CA2zBzE"}