@zenithbuild/compiler 1.3.2 → 1.3.9

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 (73) hide show
  1. package/dist/build-analyzer.d.ts +44 -0
  2. package/dist/build-analyzer.js +87 -0
  3. package/dist/bundler.d.ts +31 -0
  4. package/dist/bundler.js +92 -0
  5. package/dist/core/config/index.d.ts +11 -0
  6. package/dist/core/config/index.js +10 -0
  7. package/dist/core/config/loader.d.ts +17 -0
  8. package/dist/core/config/loader.js +60 -0
  9. package/dist/core/config/types.d.ts +98 -0
  10. package/dist/core/config/types.js +32 -0
  11. package/dist/core/index.d.ts +7 -0
  12. package/dist/core/index.js +6 -0
  13. package/dist/core/plugins/bridge.d.ts +116 -0
  14. package/dist/core/plugins/bridge.js +121 -0
  15. package/dist/core/plugins/index.d.ts +6 -0
  16. package/dist/core/plugins/index.js +6 -0
  17. package/dist/core/plugins/registry.d.ts +67 -0
  18. package/dist/core/plugins/registry.js +112 -0
  19. package/dist/css/index.d.ts +73 -0
  20. package/dist/css/index.js +246 -0
  21. package/dist/discovery/componentDiscovery.d.ts +41 -0
  22. package/dist/discovery/componentDiscovery.js +66 -0
  23. package/dist/discovery/layouts.d.ts +14 -0
  24. package/dist/discovery/layouts.js +36 -0
  25. package/dist/errors/compilerError.d.ts +31 -0
  26. package/dist/errors/compilerError.js +51 -0
  27. package/dist/finalize/generateFinalBundle.d.ts +24 -0
  28. package/dist/finalize/generateFinalBundle.js +68 -0
  29. package/dist/index.d.ts +34 -0
  30. package/dist/index.js +44 -0
  31. package/dist/ir/types.d.ts +206 -0
  32. package/dist/ir/types.js +8 -0
  33. package/dist/output/types.d.ts +39 -0
  34. package/dist/output/types.js +6 -0
  35. package/dist/parseZenFile.d.ts +17 -0
  36. package/dist/parseZenFile.js +52 -0
  37. package/dist/runtime/build.d.ts +6 -0
  38. package/dist/runtime/build.js +13 -0
  39. package/dist/runtime/bundle-generator.d.ts +27 -0
  40. package/dist/runtime/bundle-generator.js +1438 -0
  41. package/dist/runtime/client-runtime.d.ts +41 -0
  42. package/dist/runtime/client-runtime.js +397 -0
  43. package/dist/runtime/hydration.d.ts +53 -0
  44. package/dist/runtime/hydration.js +271 -0
  45. package/dist/runtime/navigation.d.ts +58 -0
  46. package/dist/runtime/navigation.js +372 -0
  47. package/dist/runtime/serve.d.ts +13 -0
  48. package/dist/runtime/serve.js +76 -0
  49. package/dist/runtime/thinRuntime.d.ts +23 -0
  50. package/dist/runtime/thinRuntime.js +158 -0
  51. package/dist/spa-build.d.ts +26 -0
  52. package/dist/spa-build.js +849 -0
  53. package/dist/ssg-build.d.ts +31 -0
  54. package/dist/ssg-build.js +429 -0
  55. package/dist/test/bundler-contract.test.d.ts +1 -0
  56. package/dist/test/bundler-contract.test.js +137 -0
  57. package/dist/test/compiler-entry.test.d.ts +1 -0
  58. package/dist/test/compiler-entry.test.js +28 -0
  59. package/dist/test/error-native-bridge.test.d.ts +1 -0
  60. package/dist/test/error-native-bridge.test.js +31 -0
  61. package/dist/test/error-serialization.test.d.ts +1 -0
  62. package/dist/test/error-serialization.test.js +38 -0
  63. package/dist/test/phase5-boundary.test.d.ts +1 -0
  64. package/dist/test/phase5-boundary.test.js +51 -0
  65. package/dist/transform/layoutProcessor.d.ts +26 -0
  66. package/dist/transform/layoutProcessor.js +34 -0
  67. package/dist/validate/invariants.d.ts +23 -0
  68. package/dist/validate/invariants.js +55 -0
  69. package/native/compiler-native/compiler-native.node +0 -0
  70. package/native/compiler-native/index.d.ts +2 -46
  71. package/native/compiler-native/index.js +1 -16
  72. package/native/compiler-native/package.json +1 -1
  73. package/package.json +15 -5
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Zenith Client Runtime - Final Canonical Implementation
3
+ * Satisfies strict reactivity requirements:
4
+ * - Signals are functions (get/set)
5
+ * - State is a Proxy
6
+ * - Effects support cleanup/debounce
7
+ * - Memos are computed signals
8
+ * - Direct DOM updates via fine-grained reactivity
9
+ */
10
+ export declare function zenSignal<T>(initialValue: T): {
11
+ (newValue?: T): T;
12
+ _isSignal: boolean;
13
+ toString(): string;
14
+ valueOf(): T;
15
+ };
16
+ export declare function zenState<T extends object>(initialObj: T): T;
17
+ export declare function zenEffect(fn: () => void | (() => void), options?: {
18
+ debounce?: number;
19
+ defer?: boolean;
20
+ }): () => void;
21
+ export declare function zenMemo<T>(fn: () => T): {
22
+ (): T;
23
+ _isSignal: boolean;
24
+ };
25
+ export declare function zenRef<T>(initial?: T): {
26
+ current: NonNullable<T> | null;
27
+ };
28
+ export declare function zenBatch(fn: () => void): void;
29
+ export declare function zenUntrack<T>(fn: () => T): T;
30
+ export interface ComponentInstance {
31
+ mountHooks: Array<() => void | (() => void)>;
32
+ }
33
+ export declare function setActiveInstance(inst: ComponentInstance | null): void;
34
+ export declare function zenOnMount(cb: any): void;
35
+ export declare function zenOnUnmount(cb: any): void;
36
+ export declare function triggerMount(inst: ComponentInstance): void;
37
+ export declare function h(tag: string, props: any, ...children: any[]): Element;
38
+ export declare function fragment(children: any): DocumentFragment;
39
+ export declare function zenLoop(sourceFn: () => any[], itemFn: (item: any, idx: number) => Node): DocumentFragment;
40
+ export declare function zenithHydrate(state: any, container?: Element | Document): void;
41
+ export declare function setup(): void;
@@ -0,0 +1,397 @@
1
+ /**
2
+ * Zenith Client Runtime - Final Canonical Implementation
3
+ * Satisfies strict reactivity requirements:
4
+ * - Signals are functions (get/set)
5
+ * - State is a Proxy
6
+ * - Effects support cleanup/debounce
7
+ * - Memos are computed signals
8
+ * - Direct DOM updates via fine-grained reactivity
9
+ */
10
+ let currentEffect = null;
11
+ const contextStack = [];
12
+ let batchDepth = 0;
13
+ const pendingEffects = new Set();
14
+ function pushContext(effect) {
15
+ contextStack.push(currentEffect);
16
+ currentEffect = effect;
17
+ }
18
+ function popContext() {
19
+ currentEffect = contextStack.pop();
20
+ }
21
+ function trackDependency(subscribers) {
22
+ if (currentEffect) {
23
+ subscribers.add(currentEffect);
24
+ currentEffect.dependencies.add(subscribers);
25
+ }
26
+ }
27
+ function notifySubscribers(subscribers) {
28
+ const effects = Array.from(subscribers);
29
+ for (const effect of effects) {
30
+ if (batchDepth > 0) {
31
+ pendingEffects.add(effect);
32
+ }
33
+ else {
34
+ effect.run();
35
+ }
36
+ }
37
+ }
38
+ function cleanupEffect(effect) {
39
+ for (const dependency of effect.dependencies) {
40
+ dependency.delete(effect);
41
+ }
42
+ effect.dependencies.clear();
43
+ }
44
+ // === zenSignal ===
45
+ export function zenSignal(initialValue) {
46
+ let value = initialValue;
47
+ const subscribers = new Set();
48
+ function signal(newValue) {
49
+ if (arguments.length === 0) {
50
+ trackDependency(subscribers);
51
+ return value;
52
+ }
53
+ if (newValue !== value) {
54
+ value = newValue;
55
+ notifySubscribers(subscribers);
56
+ }
57
+ return value;
58
+ }
59
+ signal._isSignal = true;
60
+ signal.toString = () => String(value);
61
+ signal.valueOf = () => value;
62
+ // .value getter for convenience/compat
63
+ Object.defineProperty(signal, 'value', {
64
+ get: () => signal(),
65
+ set: (v) => signal(v)
66
+ });
67
+ return signal;
68
+ }
69
+ // === zenState ===
70
+ export function zenState(initialObj) {
71
+ const subscribers = new Map();
72
+ function getSubscribers(path) {
73
+ if (!subscribers.has(path)) {
74
+ subscribers.set(path, new Set());
75
+ }
76
+ return subscribers.get(path);
77
+ }
78
+ function createProxy(obj, parentPath = '') {
79
+ if (obj === null || typeof obj !== 'object' || obj._isSignal)
80
+ return obj;
81
+ return new Proxy(obj, {
82
+ get(target, prop) {
83
+ if (typeof prop === 'symbol')
84
+ return target[prop];
85
+ const path = parentPath ? `${parentPath}.${String(prop)}` : String(prop);
86
+ trackDependency(getSubscribers(path));
87
+ const value = target[prop];
88
+ if (value !== null && typeof value === 'object' && !value._isSignal) {
89
+ return createProxy(value, path);
90
+ }
91
+ return value;
92
+ },
93
+ set(target, prop, newValue) {
94
+ if (typeof prop === 'symbol') {
95
+ target[prop] = newValue;
96
+ return true;
97
+ }
98
+ const path = parentPath ? `${parentPath}.${String(prop)}` : String(prop);
99
+ const oldValue = target[prop];
100
+ if (oldValue && typeof oldValue === 'function' && oldValue._isSignal) {
101
+ oldValue(newValue);
102
+ }
103
+ else if (oldValue !== newValue) {
104
+ target[prop] = newValue;
105
+ notifySubscribers(getSubscribers(path));
106
+ // Bubble up
107
+ const parts = path.split('.');
108
+ for (let i = parts.length - 1; i >= 0; i--) {
109
+ const pp = parts.slice(0, i).join('.');
110
+ if (pp)
111
+ notifySubscribers(getSubscribers(pp));
112
+ }
113
+ }
114
+ return true;
115
+ }
116
+ });
117
+ }
118
+ return createProxy(initialObj);
119
+ }
120
+ // === zenEffect ===
121
+ export function zenEffect(fn, options = {}) {
122
+ let cleanup;
123
+ let timeout;
124
+ const effect = {
125
+ dependencies: new Set(),
126
+ run: () => {
127
+ if (options.debounce) {
128
+ if (timeout)
129
+ clearTimeout(timeout);
130
+ timeout = setTimeout(execute, options.debounce);
131
+ }
132
+ else {
133
+ execute();
134
+ }
135
+ }
136
+ };
137
+ function execute() {
138
+ cleanupEffect(effect);
139
+ pushContext(effect);
140
+ try {
141
+ if (cleanup)
142
+ cleanup();
143
+ cleanup = fn();
144
+ }
145
+ finally {
146
+ popContext();
147
+ }
148
+ }
149
+ if (!options.defer)
150
+ execute();
151
+ return () => {
152
+ cleanupEffect(effect);
153
+ if (cleanup)
154
+ cleanup();
155
+ };
156
+ }
157
+ // === zenMemo ===
158
+ export function zenMemo(fn) {
159
+ const signal = zenSignal(undefined);
160
+ zenEffect(() => { signal(fn()); });
161
+ const memo = () => signal();
162
+ memo._isSignal = true;
163
+ return memo;
164
+ }
165
+ // === zenRef ===
166
+ export function zenRef(initial) {
167
+ return { current: initial || null };
168
+ }
169
+ // === zenBatch ===
170
+ export function zenBatch(fn) {
171
+ batchDepth++;
172
+ try {
173
+ fn();
174
+ }
175
+ finally {
176
+ batchDepth--;
177
+ if (batchDepth === 0) {
178
+ const effects = Array.from(pendingEffects);
179
+ pendingEffects.clear();
180
+ effects.forEach(e => e.run());
181
+ }
182
+ }
183
+ }
184
+ export function zenUntrack(fn) {
185
+ pushContext(null);
186
+ try {
187
+ return fn();
188
+ }
189
+ finally {
190
+ popContext();
191
+ }
192
+ }
193
+ let activeInstance = null;
194
+ export function setActiveInstance(inst) { activeInstance = inst; }
195
+ export function zenOnMount(cb) {
196
+ if (activeInstance)
197
+ activeInstance.mountHooks.push(cb);
198
+ // Fallback: if no active instance (e.g. top level), run immediately?
199
+ // Better to strict scope it, but for safety in simple usages:
200
+ else if (typeof window !== 'undefined' && document.readyState === 'complete') {
201
+ // cb(); // Uncomment if lax behavior desired
202
+ }
203
+ }
204
+ export function zenOnUnmount(cb) {
205
+ // Placeholder: requires unmount hooks in instance
206
+ }
207
+ export function triggerMount(inst) {
208
+ if (inst && inst.mountHooks) {
209
+ inst.mountHooks.forEach(cb => {
210
+ const cleanup = cb();
211
+ // TODO: Store cleanup for unmount
212
+ });
213
+ }
214
+ }
215
+ // === Rendering & Hydration ===
216
+ const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
217
+ const SVG_TAGS = new Set([
218
+ 'svg', 'path', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'rect',
219
+ 'g', 'defs', 'use', 'symbol', 'clipPath', 'mask', 'pattern', 'marker',
220
+ 'linearGradient', 'radialGradient', 'stop', 'filter', 'feGaussianBlur',
221
+ 'feOffset', 'feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite',
222
+ 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feFlood',
223
+ 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feImage', 'feMerge', 'feMergeNode',
224
+ 'feMorphology', 'fePointLight', 'feSpotLight', 'feSpecularLighting', 'feTile',
225
+ 'feTurbulence', 'foreignObject', 'image', 'switch', 'text', 'tspan', 'textPath',
226
+ 'title', 'desc', 'metadata', 'a', 'view', 'animate', 'animateMotion',
227
+ 'animateTransform', 'set', 'mpath'
228
+ ]);
229
+ // Track current namespace context for nested elements
230
+ let currentNamespace = null;
231
+ export function h(tag, props, ...children) {
232
+ // Determine if this element should be in SVG namespace
233
+ const isSvgTag = SVG_TAGS.has(tag) || SVG_TAGS.has(tag.toLowerCase());
234
+ const useSvgNamespace = isSvgTag || currentNamespace === SVG_NAMESPACE;
235
+ // Create element with correct namespace
236
+ const el = useSvgNamespace
237
+ ? document.createElementNS(SVG_NAMESPACE, tag)
238
+ : document.createElement(tag);
239
+ // Track namespace context for children
240
+ const previousNamespace = currentNamespace;
241
+ if (tag === 'svg' || tag === 'SVG') {
242
+ currentNamespace = SVG_NAMESPACE;
243
+ }
244
+ if (props) {
245
+ for (const [key, val] of Object.entries(props)) {
246
+ if (key === 'ref') {
247
+ if (val && typeof val === 'object' && 'current' in val)
248
+ val.current = el;
249
+ else if (typeof val === 'string') {
250
+ const state = window.__ZENITH_STATE__;
251
+ if (state && state[val] && typeof state[val] === 'object' && 'current' in state[val])
252
+ state[val].current = el;
253
+ }
254
+ }
255
+ else if (key.startsWith('on') && typeof val === 'function') {
256
+ el.addEventListener(key.slice(2).toLowerCase(), (e) => {
257
+ // Check if val returns a function (expression wrapper) or is the handler
258
+ const res = val(e, el);
259
+ if (typeof res === 'function')
260
+ res(e, el);
261
+ });
262
+ }
263
+ else if (typeof val === 'function') {
264
+ zenEffect(() => { updateAttr(el, key, val()); });
265
+ }
266
+ else {
267
+ updateAttr(el, key, val);
268
+ }
269
+ }
270
+ }
271
+ const spread = (items) => items.reduce((acc, v) => acc.concat(Array.isArray(v) ? spread(v) : v), []);
272
+ spread(children).forEach(child => {
273
+ if (typeof child === 'function') {
274
+ // For reactive expressions, we need a placeholder that can be updated
275
+ // The placeholder is a comment node that marks where content should go
276
+ const placeholder = document.createComment('expr');
277
+ el.appendChild(placeholder);
278
+ let currentNodes = [];
279
+ zenEffect(() => {
280
+ const result = child();
281
+ // Remove old nodes
282
+ currentNodes.forEach(n => { if (n.parentNode)
283
+ n.parentNode.removeChild(n); });
284
+ currentNodes = [];
285
+ if (result == null) {
286
+ // null/undefined - render nothing
287
+ }
288
+ else if (result instanceof Node) {
289
+ // DOM node - insert it
290
+ placeholder.before(result);
291
+ currentNodes = [result];
292
+ }
293
+ else if (Array.isArray(result)) {
294
+ // Array of nodes/strings
295
+ result.forEach(item => {
296
+ const node = item instanceof Node ? item : document.createTextNode(String(item));
297
+ placeholder.before(node);
298
+ currentNodes.push(node);
299
+ });
300
+ }
301
+ else {
302
+ // Primitive (string, number) - create text node
303
+ const textNode = document.createTextNode(String(result));
304
+ placeholder.before(textNode);
305
+ currentNodes = [textNode];
306
+ }
307
+ });
308
+ }
309
+ else {
310
+ el.appendChild(child instanceof Node ? child : document.createTextNode(String(child)));
311
+ }
312
+ });
313
+ // Restore previous namespace context
314
+ currentNamespace = previousNamespace;
315
+ return el;
316
+ }
317
+ function updateAttr(el, key, val) {
318
+ if (key === 'class' || key === 'className') {
319
+ // SVG uses className.baseVal, HTML uses className directly
320
+ if ('className' in el && typeof el.className === 'object') {
321
+ el.className.baseVal = String(val || '');
322
+ }
323
+ else {
324
+ el.className = String(val || '');
325
+ }
326
+ }
327
+ else if (key === 'style' && typeof val === 'object')
328
+ Object.assign(el.style, val);
329
+ else if (val == null || val === false)
330
+ el.removeAttribute(key);
331
+ else
332
+ el.setAttribute(key, String(val));
333
+ }
334
+ export function fragment(children) {
335
+ const frag = document.createDocumentFragment();
336
+ const items = typeof children === 'function' ? children() : children;
337
+ const spread = (its) => its.reduce((acc, v) => acc.concat(Array.isArray(v) ? spread(v) : v), []);
338
+ spread(Array.isArray(items) ? items : [items]).forEach(item => {
339
+ frag.appendChild(item instanceof Node ? item : document.createTextNode(String(item)));
340
+ });
341
+ return frag;
342
+ }
343
+ export function zenLoop(sourceFn, itemFn) {
344
+ const start = document.createComment('loop:start');
345
+ const end = document.createComment('loop:end');
346
+ const frag = document.createDocumentFragment();
347
+ frag.append(start, end);
348
+ zenEffect(() => {
349
+ const items = sourceFn() || [];
350
+ let curr = start.nextSibling;
351
+ while (curr && curr !== end) {
352
+ const next = curr.nextSibling;
353
+ curr.remove();
354
+ curr = next;
355
+ }
356
+ items.forEach((item, i) => end.before(itemFn(item, i)));
357
+ });
358
+ return frag;
359
+ }
360
+ export function zenithHydrate(state, container = document) {
361
+ const ir = window.canonicalIR;
362
+ if (!ir)
363
+ return;
364
+ window.__ZENITH_STATE__ = state;
365
+ const nodes = ir(state);
366
+ const mount = container === document ? document.body : container;
367
+ mount.innerHTML = '';
368
+ const arr = Array.isArray(nodes) ? nodes : [nodes];
369
+ arr.forEach(n => {
370
+ if (n == null || n === false)
371
+ return;
372
+ // If it's a full <html> node, we might need to be more careful,
373
+ // but for now let's just avoid stringifying nulls.
374
+ mount.appendChild(n instanceof Node ? n : document.createTextNode(String(n)));
375
+ });
376
+ }
377
+ // === Global Setup ===
378
+ export function setup() {
379
+ if (typeof window === 'undefined')
380
+ return;
381
+ const w = window;
382
+ w.__zenith = { h, fragment, loop: zenLoop, state: zenState, signal: zenSignal, effect: zenEffect, memo: zenMemo, ref: zenRef, batch: zenBatch, onMount: zenOnMount, setActiveInstance, triggerMount, spread_children: (a) => a };
383
+ w.zenithHydrate = zenithHydrate;
384
+ // Expose globals for imported usage
385
+ w.zenSignal = zenSignal;
386
+ w.zenState = zenState;
387
+ w.zenEffect = zenEffect;
388
+ w.zenMemo = zenMemo;
389
+ w.zenRef = zenRef;
390
+ w.zenBatch = zenBatch;
391
+ w.zenUntrack = zenUntrack;
392
+ w.zenOnMount = zenOnMount;
393
+ // [ZENITH-NATIVE] zenOrder: Scheduling primitive
394
+ w.zenOrder = (fn) => { if (typeof fn === 'function')
395
+ fn(); };
396
+ }
397
+ setup();
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Runtime Hydration Layer
3
+ *
4
+ * Phase 5: Browser-side runtime that hydrates static HTML with dynamic expressions
5
+ *
6
+ * This runtime:
7
+ * - Locates DOM placeholders (data-zen-text, data-zen-attr-*)
8
+ * - Evaluates precompiled expressions against state
9
+ * - Updates DOM textContent, attributes, and properties
10
+ * - Binds event handlers
11
+ * - Handles reactive state updates
12
+ */
13
+ /**
14
+ * Expression registry - maps expression IDs to their evaluation functions
15
+ * Populated at runtime with compiled expressions
16
+ */
17
+ declare global {
18
+ interface Window {
19
+ __ZENITH_EXPRESSIONS__?: Map<string, (state: any) => any>;
20
+ __ZENITH_STATE__?: any;
21
+ }
22
+ }
23
+ /**
24
+ * Hydrate static HTML with dynamic expressions
25
+ *
26
+ * @param state - The state object to evaluate expressions against
27
+ * @param container - The container element to hydrate (defaults to document)
28
+ */
29
+ export declare function hydrate(state: any, container?: Document | Element): void;
30
+ /**
31
+ * Bind event handlers to DOM elements
32
+ *
33
+ * @param container - The container element to bind events in (defaults to document)
34
+ */
35
+ export declare function bindEvents(container?: Document | Element): void;
36
+ /**
37
+ * Update all bindings when state changes
38
+ *
39
+ * @param state - The new state object
40
+ */
41
+ export declare function update(state: any): void;
42
+ /**
43
+ * Initialize the expression registry
44
+ * Called once when the runtime loads
45
+ *
46
+ * @param expressions - Map of expression IDs to evaluation functions
47
+ */
48
+ export declare function initExpressions(expressions: Map<string, (state: any) => any>): void;
49
+ /**
50
+ * Clear all bindings and event listeners
51
+ * Useful for cleanup when navigating away
52
+ */
53
+ export declare function cleanup(container?: Document | Element): void;