@zenithbuild/compiler 1.0.15 → 1.3.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 (144) hide show
  1. package/native/compiler-native/compiler-native.node +0 -0
  2. package/native/compiler-native/index.d.ts +46 -7
  3. package/native/compiler-native/index.js +332 -17
  4. package/package.json +3 -3
  5. package/dist/build-analyzer.d.ts +0 -44
  6. package/dist/build-analyzer.js +0 -87
  7. package/dist/bundler.d.ts +0 -31
  8. package/dist/bundler.js +0 -86
  9. package/dist/compiler-native-ep39xj7a.node +0 -0
  10. package/dist/compiler-native-ftk9z446.node +0 -0
  11. package/dist/core/components/index.d.ts +0 -9
  12. package/dist/core/components/index.js +0 -13
  13. package/dist/core/config/index.d.ts +0 -11
  14. package/dist/core/config/index.js +0 -10
  15. package/dist/core/config/loader.d.ts +0 -17
  16. package/dist/core/config/loader.js +0 -60
  17. package/dist/core/config/types.d.ts +0 -98
  18. package/dist/core/config/types.js +0 -32
  19. package/dist/core/index.d.ts +0 -7
  20. package/dist/core/index.js +0 -6
  21. package/dist/core/lifecycle/index.d.ts +0 -16
  22. package/dist/core/lifecycle/index.js +0 -19
  23. package/dist/core/lifecycle/zen-mount.d.ts +0 -66
  24. package/dist/core/lifecycle/zen-mount.js +0 -151
  25. package/dist/core/lifecycle/zen-unmount.d.ts +0 -54
  26. package/dist/core/lifecycle/zen-unmount.js +0 -76
  27. package/dist/core/plugins/bridge.d.ts +0 -116
  28. package/dist/core/plugins/bridge.js +0 -121
  29. package/dist/core/plugins/index.d.ts +0 -6
  30. package/dist/core/plugins/index.js +0 -6
  31. package/dist/core/plugins/registry.d.ts +0 -67
  32. package/dist/core/plugins/registry.js +0 -112
  33. package/dist/core/reactivity/index.d.ts +0 -30
  34. package/dist/core/reactivity/index.js +0 -33
  35. package/dist/core/reactivity/tracking.d.ts +0 -74
  36. package/dist/core/reactivity/tracking.js +0 -136
  37. package/dist/core/reactivity/zen-batch.d.ts +0 -45
  38. package/dist/core/reactivity/zen-batch.js +0 -54
  39. package/dist/core/reactivity/zen-effect.d.ts +0 -48
  40. package/dist/core/reactivity/zen-effect.js +0 -98
  41. package/dist/core/reactivity/zen-memo.d.ts +0 -43
  42. package/dist/core/reactivity/zen-memo.js +0 -100
  43. package/dist/core/reactivity/zen-ref.d.ts +0 -44
  44. package/dist/core/reactivity/zen-ref.js +0 -34
  45. package/dist/core/reactivity/zen-signal.d.ts +0 -48
  46. package/dist/core/reactivity/zen-signal.js +0 -84
  47. package/dist/core/reactivity/zen-state.d.ts +0 -35
  48. package/dist/core/reactivity/zen-state.js +0 -147
  49. package/dist/core/reactivity/zen-untrack.d.ts +0 -38
  50. package/dist/core/reactivity/zen-untrack.js +0 -41
  51. package/dist/css/index.d.ts +0 -73
  52. package/dist/css/index.js +0 -246
  53. package/dist/discovery/componentDiscovery.d.ts +0 -42
  54. package/dist/discovery/componentDiscovery.js +0 -56
  55. package/dist/discovery/layouts.d.ts +0 -13
  56. package/dist/discovery/layouts.js +0 -41
  57. package/dist/errors/compilerError.d.ts +0 -31
  58. package/dist/errors/compilerError.js +0 -51
  59. package/dist/finalize/finalizeOutput.d.ts +0 -32
  60. package/dist/finalize/finalizeOutput.js +0 -62
  61. package/dist/finalize/generateFinalBundle.d.ts +0 -24
  62. package/dist/finalize/generateFinalBundle.js +0 -68
  63. package/dist/index.d.ts +0 -38
  64. package/dist/index.js +0 -57
  65. package/dist/ir/types.d.ts +0 -181
  66. package/dist/ir/types.js +0 -8
  67. package/dist/output/types.d.ts +0 -30
  68. package/dist/output/types.js +0 -6
  69. package/dist/parse/detectMapExpressions.d.ts +0 -45
  70. package/dist/parse/detectMapExpressions.js +0 -77
  71. package/dist/parse/parseScript.d.ts +0 -8
  72. package/dist/parse/parseScript.js +0 -36
  73. package/dist/parse/parseTemplate.d.ts +0 -11
  74. package/dist/parse/parseTemplate.js +0 -487
  75. package/dist/parse/parseZenFile.d.ts +0 -11
  76. package/dist/parse/parseZenFile.js +0 -50
  77. package/dist/parse/scriptAnalysis.d.ts +0 -25
  78. package/dist/parse/scriptAnalysis.js +0 -60
  79. package/dist/parse/trackLoopContext.d.ts +0 -20
  80. package/dist/parse/trackLoopContext.js +0 -62
  81. package/dist/parseZenFile.d.ts +0 -10
  82. package/dist/parseZenFile.js +0 -55
  83. package/dist/runtime/analyzeAndEmit.d.ts +0 -20
  84. package/dist/runtime/analyzeAndEmit.js +0 -70
  85. package/dist/runtime/build.d.ts +0 -6
  86. package/dist/runtime/build.js +0 -13
  87. package/dist/runtime/bundle-generator.d.ts +0 -27
  88. package/dist/runtime/bundle-generator.js +0 -1438
  89. package/dist/runtime/client-runtime.d.ts +0 -41
  90. package/dist/runtime/client-runtime.js +0 -397
  91. package/dist/runtime/dataExposure.d.ts +0 -52
  92. package/dist/runtime/dataExposure.js +0 -227
  93. package/dist/runtime/generateDOM.d.ts +0 -21
  94. package/dist/runtime/generateDOM.js +0 -194
  95. package/dist/runtime/generateHydrationBundle.d.ts +0 -15
  96. package/dist/runtime/generateHydrationBundle.js +0 -399
  97. package/dist/runtime/hydration.d.ts +0 -53
  98. package/dist/runtime/hydration.js +0 -271
  99. package/dist/runtime/navigation.d.ts +0 -58
  100. package/dist/runtime/navigation.js +0 -372
  101. package/dist/runtime/serve.d.ts +0 -13
  102. package/dist/runtime/serve.js +0 -76
  103. package/dist/runtime/thinRuntime.d.ts +0 -23
  104. package/dist/runtime/thinRuntime.js +0 -158
  105. package/dist/runtime/transformIR.d.ts +0 -19
  106. package/dist/runtime/transformIR.js +0 -285
  107. package/dist/runtime/wrapExpression.d.ts +0 -24
  108. package/dist/runtime/wrapExpression.js +0 -76
  109. package/dist/runtime/wrapExpressionWithLoop.d.ts +0 -17
  110. package/dist/runtime/wrapExpressionWithLoop.js +0 -75
  111. package/dist/spa-build.d.ts +0 -26
  112. package/dist/spa-build.js +0 -857
  113. package/dist/ssg-build.d.ts +0 -32
  114. package/dist/ssg-build.js +0 -408
  115. package/dist/test/analyze-emit.test.d.ts +0 -1
  116. package/dist/test/analyze-emit.test.js +0 -88
  117. package/dist/test/bundler-contract.test.d.ts +0 -1
  118. package/dist/test/bundler-contract.test.js +0 -137
  119. package/dist/test/compiler-authority.test.d.ts +0 -1
  120. package/dist/test/compiler-authority.test.js +0 -90
  121. package/dist/test/component-instance-test.d.ts +0 -1
  122. package/dist/test/component-instance-test.js +0 -115
  123. package/dist/test/error-native-bridge.test.d.ts +0 -1
  124. package/dist/test/error-native-bridge.test.js +0 -51
  125. package/dist/test/error-serialization.test.d.ts +0 -1
  126. package/dist/test/error-serialization.test.js +0 -38
  127. package/dist/test/macro-inlining.test.d.ts +0 -1
  128. package/dist/test/macro-inlining.test.js +0 -178
  129. package/dist/test/validate-test.d.ts +0 -6
  130. package/dist/test/validate-test.js +0 -95
  131. package/dist/transform/classifyExpression.d.ts +0 -46
  132. package/dist/transform/classifyExpression.js +0 -359
  133. package/dist/transform/componentResolver.d.ts +0 -15
  134. package/dist/transform/componentResolver.js +0 -24
  135. package/dist/transform/expressionTransformer.d.ts +0 -19
  136. package/dist/transform/expressionTransformer.js +0 -333
  137. package/dist/transform/fragmentLowering.d.ts +0 -25
  138. package/dist/transform/fragmentLowering.js +0 -468
  139. package/dist/transform/layoutProcessor.d.ts +0 -5
  140. package/dist/transform/layoutProcessor.js +0 -34
  141. package/dist/transform/transformTemplate.d.ts +0 -11
  142. package/dist/transform/transformTemplate.js +0 -33
  143. package/dist/validate/invariants.d.ts +0 -23
  144. package/dist/validate/invariants.js +0 -55
@@ -1,84 +0,0 @@
1
- /**
2
- * Zenith Signal - Atomic Reactive Value
3
- *
4
- * A signal is the most basic reactive primitive. It holds a single value
5
- * and notifies subscribers when the value changes.
6
- *
7
- * Features:
8
- * - Getter/setter model
9
- * - Automatic dependency tracking
10
- * - Fine-grained reactivity (no component re-rendering)
11
- *
12
- * @example
13
- * ```ts
14
- * const count = zenSignal(0)
15
- *
16
- * // Read value
17
- * console.log(count()) // 0
18
- *
19
- * // Write value
20
- * count(1)
21
- *
22
- * // Or use .value
23
- * count.value = 2
24
- * console.log(count.value) // 2
25
- * ```
26
- */
27
- import { trackDependency, notifySubscribers } from './tracking';
28
- /**
29
- * Create a reactive signal
30
- *
31
- * @param initialValue - The initial value of the signal
32
- * @returns A signal that can be read and written
33
- */
34
- export function zenSignal(initialValue) {
35
- const state = {
36
- value: initialValue,
37
- subscribers: new Set()
38
- };
39
- // The signal function - acts as both getter and setter
40
- function signal(newValue) {
41
- if (arguments.length === 0) {
42
- // Getter - track dependency and return value
43
- trackDependency(state.subscribers);
44
- return state.value;
45
- }
46
- else {
47
- // Setter - update value and notify
48
- const oldValue = state.value;
49
- state.value = newValue;
50
- if (!Object.is(oldValue, newValue)) {
51
- notifySubscribers(state.subscribers);
52
- }
53
- return state.value;
54
- }
55
- }
56
- // Add .value accessor
57
- Object.defineProperty(signal, 'value', {
58
- get() {
59
- trackDependency(state.subscribers);
60
- return state.value;
61
- },
62
- set(newValue) {
63
- const oldValue = state.value;
64
- state.value = newValue;
65
- if (!Object.is(oldValue, newValue)) {
66
- notifySubscribers(state.subscribers);
67
- }
68
- },
69
- enumerable: true,
70
- configurable: false
71
- });
72
- signal.peek = function () {
73
- return state.value;
74
- };
75
- signal.subscribe = function (fn) {
76
- const subscriber = () => fn(state.value);
77
- state.subscribers.add(subscriber);
78
- // Return unsubscribe function
79
- return () => {
80
- state.subscribers.delete(subscriber);
81
- };
82
- };
83
- return signal;
84
- }
@@ -1,35 +0,0 @@
1
- /**
2
- * Zenith State - Deep Reactive Object
3
- *
4
- * Creates a deeply reactive object using Proxy. Any property access
5
- * is tracked, and any mutation triggers effects.
6
- *
7
- * Features:
8
- * - Deep reactivity via nested Proxies
9
- * - Automatic dependency tracking on property access
10
- * - Triggers effects on property mutation
11
- *
12
- * @example
13
- * ```ts
14
- * const user = zenState({
15
- * name: 'John',
16
- * address: {
17
- * city: 'NYC'
18
- * }
19
- * })
20
- *
21
- * // Access triggers tracking
22
- * console.log(user.name)
23
- *
24
- * // Mutation triggers effects
25
- * user.name = 'Jane'
26
- * user.address.city = 'LA'
27
- * ```
28
- */
29
- /**
30
- * Create a deeply reactive state object
31
- *
32
- * @param initialValue - The initial state object
33
- * @returns A reactive proxy of the object
34
- */
35
- export declare function zenState<T extends object>(initialValue: T): T;
@@ -1,147 +0,0 @@
1
- /**
2
- * Zenith State - Deep Reactive Object
3
- *
4
- * Creates a deeply reactive object using Proxy. Any property access
5
- * is tracked, and any mutation triggers effects.
6
- *
7
- * Features:
8
- * - Deep reactivity via nested Proxies
9
- * - Automatic dependency tracking on property access
10
- * - Triggers effects on property mutation
11
- *
12
- * @example
13
- * ```ts
14
- * const user = zenState({
15
- * name: 'John',
16
- * address: {
17
- * city: 'NYC'
18
- * }
19
- * })
20
- *
21
- * // Access triggers tracking
22
- * console.log(user.name)
23
- *
24
- * // Mutation triggers effects
25
- * user.name = 'Jane'
26
- * user.address.city = 'LA'
27
- * ```
28
- */
29
- import { trackDependency, notifySubscribers } from './tracking';
30
- /**
31
- * WeakMap to store proxy targets and their subscriber maps
32
- * Key: target object
33
- * Value: Map of property key -> subscriber set
34
- */
35
- const proxySubscribers = new WeakMap();
36
- /**
37
- * WeakMap to store original objects and their proxies
38
- * Prevents creating multiple proxies for the same object
39
- */
40
- const proxyCache = new WeakMap();
41
- /**
42
- * Get or create subscriber set for a property
43
- */
44
- function getPropertySubscribers(target, key) {
45
- let propertyMap = proxySubscribers.get(target);
46
- if (!propertyMap) {
47
- propertyMap = new Map();
48
- proxySubscribers.set(target, propertyMap);
49
- }
50
- let subscribers = propertyMap.get(key);
51
- if (!subscribers) {
52
- subscribers = new Set();
53
- propertyMap.set(key, subscribers);
54
- }
55
- return subscribers;
56
- }
57
- /**
58
- * Check if a value should be wrapped in a proxy
59
- */
60
- function shouldProxy(value) {
61
- if (value === null || typeof value !== 'object') {
62
- return false;
63
- }
64
- // Don't proxy special objects
65
- if (value instanceof Date ||
66
- value instanceof RegExp ||
67
- value instanceof Map ||
68
- value instanceof Set ||
69
- value instanceof WeakMap ||
70
- value instanceof WeakSet ||
71
- value instanceof Promise ||
72
- ArrayBuffer.isView(value)) {
73
- return false;
74
- }
75
- return true;
76
- }
77
- /**
78
- * Create a reactive proxy for an object
79
- */
80
- function createReactiveProxy(target) {
81
- // Check cache first
82
- const cached = proxyCache.get(target);
83
- if (cached) {
84
- return cached;
85
- }
86
- const proxy = new Proxy(target, {
87
- get(target, key, receiver) {
88
- // Track dependency
89
- const subscribers = getPropertySubscribers(target, key);
90
- trackDependency(subscribers);
91
- const value = Reflect.get(target, key, receiver);
92
- // Recursively proxy nested objects
93
- if (shouldProxy(value)) {
94
- return createReactiveProxy(value);
95
- }
96
- return value;
97
- },
98
- set(target, key, value, receiver) {
99
- const oldValue = Reflect.get(target, key, receiver);
100
- // Unwrap proxies before storing
101
- const rawValue = value;
102
- const result = Reflect.set(target, key, rawValue, receiver);
103
- // Only notify if value actually changed
104
- if (!Object.is(oldValue, rawValue)) {
105
- const subscribers = getPropertySubscribers(target, key);
106
- notifySubscribers(subscribers);
107
- }
108
- return result;
109
- },
110
- deleteProperty(target, key) {
111
- const hadKey = Reflect.has(target, key);
112
- const result = Reflect.deleteProperty(target, key);
113
- if (hadKey && result) {
114
- const subscribers = getPropertySubscribers(target, key);
115
- notifySubscribers(subscribers);
116
- }
117
- return result;
118
- },
119
- has(target, key) {
120
- // Track dependency for 'in' operator
121
- const subscribers = getPropertySubscribers(target, key);
122
- trackDependency(subscribers);
123
- return Reflect.has(target, key);
124
- },
125
- ownKeys(target) {
126
- // Track a special 'keys' dependency for iteration
127
- const subscribers = getPropertySubscribers(target, Symbol.for('zen:keys'));
128
- trackDependency(subscribers);
129
- return Reflect.ownKeys(target);
130
- }
131
- });
132
- // Cache the proxy
133
- proxyCache.set(target, proxy);
134
- return proxy;
135
- }
136
- /**
137
- * Create a deeply reactive state object
138
- *
139
- * @param initialValue - The initial state object
140
- * @returns A reactive proxy of the object
141
- */
142
- export function zenState(initialValue) {
143
- if (!shouldProxy(initialValue)) {
144
- throw new Error('zenState requires a plain object or array');
145
- }
146
- return createReactiveProxy(initialValue);
147
- }
@@ -1,38 +0,0 @@
1
- /**
2
- * Zenith Untrack - Escape Dependency Tracking
3
- *
4
- * Allows reading reactive values without creating a dependency.
5
- * Useful when you need to read a value inside an effect but don't
6
- * want the effect to re-run when that value changes.
7
- *
8
- * Features:
9
- * - Disables dependency tracking within the callback
10
- * - Returns the callback's return value
11
- * - Can be nested
12
- *
13
- * @example
14
- * ```ts
15
- * const count = zenSignal(0)
16
- * const multiplier = zenSignal(2)
17
- *
18
- * zenEffect(() => {
19
- * // This creates a dependency on 'count'
20
- * const c = count()
21
- *
22
- * // This does NOT create a dependency on 'multiplier'
23
- * const m = zenUntrack(() => multiplier())
24
- *
25
- * console.log(c * m)
26
- * })
27
- *
28
- * count(5) // Effect re-runs
29
- * multiplier(3) // Effect does NOT re-run
30
- * ```
31
- */
32
- /**
33
- * Execute a function without tracking dependencies
34
- *
35
- * @param fn - The function to execute
36
- * @returns The return value of the function
37
- */
38
- export declare function zenUntrack<T>(fn: () => T): T;
@@ -1,41 +0,0 @@
1
- /**
2
- * Zenith Untrack - Escape Dependency Tracking
3
- *
4
- * Allows reading reactive values without creating a dependency.
5
- * Useful when you need to read a value inside an effect but don't
6
- * want the effect to re-run when that value changes.
7
- *
8
- * Features:
9
- * - Disables dependency tracking within the callback
10
- * - Returns the callback's return value
11
- * - Can be nested
12
- *
13
- * @example
14
- * ```ts
15
- * const count = zenSignal(0)
16
- * const multiplier = zenSignal(2)
17
- *
18
- * zenEffect(() => {
19
- * // This creates a dependency on 'count'
20
- * const c = count()
21
- *
22
- * // This does NOT create a dependency on 'multiplier'
23
- * const m = zenUntrack(() => multiplier())
24
- *
25
- * console.log(c * m)
26
- * })
27
- *
28
- * count(5) // Effect re-runs
29
- * multiplier(3) // Effect does NOT re-run
30
- * ```
31
- */
32
- import { runUntracked } from './tracking';
33
- /**
34
- * Execute a function without tracking dependencies
35
- *
36
- * @param fn - The function to execute
37
- * @returns The return value of the function
38
- */
39
- export function zenUntrack(fn) {
40
- return runUntracked(fn);
41
- }
@@ -1,73 +0,0 @@
1
- /**
2
- * Zenith CSS Compiler Module
3
- *
4
- * Compiler-owned CSS processing that integrates Tailwind CSS v4 JIT
5
- * at compile time. This module ensures:
6
- *
7
- * 1. All CSS is processed at build time (no runtime generation)
8
- * 2. Tailwind sees all .zen templates for class scanning
9
- * 3. HMR support for instant CSS updates in dev mode
10
- * 4. Deterministic, cacheable output for production
11
- *
12
- * Per Zenith CSS Directive: The compiler owns styles.
13
- */
14
- export interface CSSCompileOptions {
15
- /** Input CSS file path (e.g., src/styles/globals.css) */
16
- input: string;
17
- /** Output CSS file path, or ':memory:' for in-memory result */
18
- output: string;
19
- /** Enable minification for production */
20
- minify?: boolean;
21
- /** Watch mode for HMR */
22
- watch?: boolean;
23
- }
24
- export interface CSSCompileResult {
25
- /** Compiled CSS content */
26
- css: string;
27
- /** Compilation time in milliseconds */
28
- duration: number;
29
- /** Whether compilation succeeded */
30
- success: boolean;
31
- /** Error message if failed */
32
- error?: string;
33
- }
34
- /**
35
- * Compile CSS using Tailwind CSS v4 CLI
36
- *
37
- * This function synchronously compiles CSS for use in:
38
- * - Dev server startup
39
- * - SSG build
40
- * - On-demand recompilation
41
- *
42
- * @param options Compilation options
43
- * @returns Compiled CSS result
44
- */
45
- export declare function compileCss(options: CSSCompileOptions): CSSCompileResult;
46
- /**
47
- * Compile CSS asynchronously (non-blocking)
48
- *
49
- * Used for HMR updates where we don't want to block the main thread.
50
- */
51
- export declare function compileCssAsync(options: CSSCompileOptions): Promise<CSSCompileResult>;
52
- export interface CSSWatchOptions extends CSSCompileOptions {
53
- /** Callback when CSS changes */
54
- onChange: (result: CSSCompileResult) => void;
55
- /** Debounce delay in ms */
56
- debounce?: number;
57
- }
58
- /**
59
- * Watch CSS and source files for changes, recompile on change
60
- *
61
- * This is used by the dev server for HMR support.
62
- * It watches both the CSS entry point AND all .zen files
63
- * that Tailwind scans for class names.
64
- */
65
- export declare function watchCss(options: CSSWatchOptions): () => void;
66
- /**
67
- * Resolve the canonical globals.css path for a Zenith project
68
- */
69
- export declare function resolveGlobalsCss(projectRoot: string): string | null;
70
- /**
71
- * Get the output path for compiled CSS
72
- */
73
- export declare function getCompiledCssPath(projectRoot: string, mode: 'dev' | 'build'): string;
package/dist/css/index.js DELETED
@@ -1,246 +0,0 @@
1
- /**
2
- * Zenith CSS Compiler Module
3
- *
4
- * Compiler-owned CSS processing that integrates Tailwind CSS v4 JIT
5
- * at compile time. This module ensures:
6
- *
7
- * 1. All CSS is processed at build time (no runtime generation)
8
- * 2. Tailwind sees all .zen templates for class scanning
9
- * 3. HMR support for instant CSS updates in dev mode
10
- * 4. Deterministic, cacheable output for production
11
- *
12
- * Per Zenith CSS Directive: The compiler owns styles.
13
- */
14
- import { spawn, spawnSync } from 'child_process';
15
- import path from 'path';
16
- import fs from 'fs';
17
- // ============================================
18
- // CSS Compilation
19
- // ============================================
20
- /**
21
- * Compile CSS using Tailwind CSS v4 CLI
22
- *
23
- * This function synchronously compiles CSS for use in:
24
- * - Dev server startup
25
- * - SSG build
26
- * - On-demand recompilation
27
- *
28
- * @param options Compilation options
29
- * @returns Compiled CSS result
30
- */
31
- export function compileCss(options) {
32
- const startTime = performance.now();
33
- const { input, output, minify = false } = options;
34
- // Validate input exists
35
- if (!fs.existsSync(input)) {
36
- return {
37
- css: '',
38
- duration: 0,
39
- success: false,
40
- error: `CSS input file not found: ${input}`
41
- };
42
- }
43
- try {
44
- // Build Tailwind CLI arguments
45
- const args = [
46
- '@tailwindcss/cli',
47
- '-i', input
48
- ];
49
- // For in-memory compilation, use stdout
50
- const useStdout = output === ':memory:';
51
- if (!useStdout) {
52
- args.push('-o', output);
53
- }
54
- if (minify) {
55
- args.push('--minify');
56
- }
57
- // Execute Tailwind CLI synchronously
58
- const result = spawnSync('bunx', args, {
59
- cwd: path.dirname(input),
60
- encoding: 'utf-8',
61
- stdio: useStdout ? ['pipe', 'pipe', 'pipe'] : ['pipe', 'inherit', 'pipe'],
62
- env: { ...process.env }
63
- });
64
- const duration = Math.round(performance.now() - startTime);
65
- if (result.status !== 0) {
66
- const errorMsg = result.stderr?.toString() || 'Unknown compilation error';
67
- return {
68
- css: '',
69
- duration,
70
- success: false,
71
- error: `Tailwind compilation failed: ${errorMsg}`
72
- };
73
- }
74
- // Get CSS content
75
- let css = '';
76
- if (useStdout) {
77
- css = result.stdout?.toString() || '';
78
- }
79
- else if (fs.existsSync(output)) {
80
- css = fs.readFileSync(output, 'utf-8');
81
- }
82
- return {
83
- css,
84
- duration,
85
- success: true
86
- };
87
- }
88
- catch (error) {
89
- return {
90
- css: '',
91
- duration: Math.round(performance.now() - startTime),
92
- success: false,
93
- error: error.message
94
- };
95
- }
96
- }
97
- /**
98
- * Compile CSS asynchronously (non-blocking)
99
- *
100
- * Used for HMR updates where we don't want to block the main thread.
101
- */
102
- export async function compileCssAsync(options) {
103
- return new Promise((resolve) => {
104
- const startTime = performance.now();
105
- const { input, output, minify = false } = options;
106
- if (!fs.existsSync(input)) {
107
- resolve({
108
- css: '',
109
- duration: 0,
110
- success: false,
111
- error: `CSS input file not found: ${input}`
112
- });
113
- return;
114
- }
115
- const args = ['@tailwindcss/cli', '-i', input];
116
- const useStdout = output === ':memory:';
117
- if (!useStdout) {
118
- args.push('-o', output);
119
- }
120
- if (minify) {
121
- args.push('--minify');
122
- }
123
- const child = spawn('bunx', args, {
124
- cwd: path.dirname(input),
125
- stdio: useStdout ? ['pipe', 'pipe', 'pipe'] : ['pipe', 'inherit', 'pipe'],
126
- env: { ...process.env }
127
- });
128
- let stdout = '';
129
- let stderr = '';
130
- if (useStdout && child.stdout) {
131
- child.stdout.on('data', (data) => { stdout += data.toString(); });
132
- }
133
- if (child.stderr) {
134
- child.stderr.on('data', (data) => { stderr += data.toString(); });
135
- }
136
- child.on('close', (code) => {
137
- const duration = Math.round(performance.now() - startTime);
138
- if (code !== 0) {
139
- resolve({
140
- css: '',
141
- duration,
142
- success: false,
143
- error: `Tailwind compilation failed: ${stderr}`
144
- });
145
- return;
146
- }
147
- let css = '';
148
- if (useStdout) {
149
- css = stdout;
150
- }
151
- else if (fs.existsSync(output)) {
152
- css = fs.readFileSync(output, 'utf-8');
153
- }
154
- resolve({
155
- css,
156
- duration,
157
- success: true
158
- });
159
- });
160
- child.on('error', (err) => {
161
- resolve({
162
- css: '',
163
- duration: Math.round(performance.now() - startTime),
164
- success: false,
165
- error: err.message
166
- });
167
- });
168
- });
169
- }
170
- /**
171
- * Watch CSS and source files for changes, recompile on change
172
- *
173
- * This is used by the dev server for HMR support.
174
- * It watches both the CSS entry point AND all .zen files
175
- * that Tailwind scans for class names.
176
- */
177
- export function watchCss(options) {
178
- const { input, output, minify, onChange, debounce = 100 } = options;
179
- let timeout = null;
180
- let isCompiling = false;
181
- const recompile = async () => {
182
- if (isCompiling)
183
- return;
184
- isCompiling = true;
185
- const result = await compileCssAsync({ input, output, minify });
186
- onChange(result);
187
- isCompiling = false;
188
- };
189
- const debouncedRecompile = () => {
190
- if (timeout)
191
- clearTimeout(timeout);
192
- timeout = setTimeout(recompile, debounce);
193
- };
194
- // Watch the styles directory
195
- const stylesDir = path.dirname(input);
196
- const stylesWatcher = fs.watch(stylesDir, { recursive: true }, (event, filename) => {
197
- if (filename?.endsWith('.css')) {
198
- debouncedRecompile();
199
- }
200
- });
201
- // Watch source files that Tailwind scans (for class changes)
202
- // This assumes standard Zenith structure: src/pages, src/components, src/layouts
203
- const srcDir = path.resolve(stylesDir, '..');
204
- let srcWatcher = null;
205
- if (fs.existsSync(srcDir)) {
206
- srcWatcher = fs.watch(srcDir, { recursive: true }, (event, filename) => {
207
- if (filename?.endsWith('.zen') || filename?.endsWith('.tsx') || filename?.endsWith('.jsx')) {
208
- debouncedRecompile();
209
- }
210
- });
211
- }
212
- // Return cleanup function
213
- return () => {
214
- if (timeout)
215
- clearTimeout(timeout);
216
- stylesWatcher.close();
217
- srcWatcher?.close();
218
- };
219
- }
220
- // ============================================
221
- // Path Utilities
222
- // ============================================
223
- /**
224
- * Resolve the canonical globals.css path for a Zenith project
225
- */
226
- export function resolveGlobalsCss(projectRoot) {
227
- // Check for globals.css (canonical)
228
- const globalsPath = path.join(projectRoot, 'src', 'styles', 'globals.css');
229
- if (fs.existsSync(globalsPath))
230
- return globalsPath;
231
- // Check for global.css (legacy)
232
- const globalPath = path.join(projectRoot, 'src', 'styles', 'global.css');
233
- if (fs.existsSync(globalPath))
234
- return globalPath;
235
- return null;
236
- }
237
- /**
238
- * Get the output path for compiled CSS
239
- */
240
- export function getCompiledCssPath(projectRoot, mode) {
241
- if (mode === 'build') {
242
- return path.join(projectRoot, 'dist', 'assets', 'styles.css');
243
- }
244
- // In dev mode, we use in-memory compilation
245
- return ':memory:';
246
- }