@zenithbuild/core 0.1.0 → 0.3.1

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 (90) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +24 -40
  3. package/bin/zen-build.ts +2 -0
  4. package/bin/zen-dev.ts +2 -0
  5. package/bin/zen-preview.ts +2 -0
  6. package/bin/zenith.ts +2 -0
  7. package/cli/commands/add.ts +37 -0
  8. package/cli/commands/build.ts +37 -0
  9. package/cli/commands/create.ts +702 -0
  10. package/cli/commands/dev.ts +197 -0
  11. package/cli/commands/index.ts +112 -0
  12. package/cli/commands/preview.ts +62 -0
  13. package/cli/commands/remove.ts +33 -0
  14. package/cli/index.ts +10 -0
  15. package/cli/main.ts +101 -0
  16. package/cli/utils/branding.ts +153 -0
  17. package/cli/utils/logger.ts +40 -0
  18. package/cli/utils/plugin-manager.ts +114 -0
  19. package/cli/utils/project.ts +71 -0
  20. package/compiler/build-analyzer.ts +122 -0
  21. package/compiler/discovery/layouts.ts +61 -0
  22. package/compiler/index.ts +40 -24
  23. package/compiler/ir/types.ts +1 -0
  24. package/compiler/parse/parseScript.ts +29 -5
  25. package/compiler/parse/parseTemplate.ts +96 -58
  26. package/compiler/parse/scriptAnalysis.ts +77 -0
  27. package/compiler/runtime/dataExposure.ts +49 -31
  28. package/compiler/runtime/generateDOM.ts +18 -17
  29. package/compiler/runtime/generateHydrationBundle.ts +24 -5
  30. package/compiler/runtime/transformIR.ts +140 -49
  31. package/compiler/runtime/wrapExpressionWithLoop.ts +11 -11
  32. package/compiler/spa-build.ts +70 -153
  33. package/compiler/ssg-build.ts +412 -0
  34. package/compiler/transform/layoutProcessor.ts +132 -0
  35. package/compiler/transform/transformNode.ts +19 -19
  36. package/dist/cli.js +11648 -0
  37. package/dist/zen-build.js +11659 -0
  38. package/dist/zen-dev.js +11659 -0
  39. package/dist/zen-preview.js +11659 -0
  40. package/dist/zenith.js +11659 -0
  41. package/package.json +22 -2
  42. package/runtime/bundle-generator.ts +416 -0
  43. package/runtime/client-runtime.ts +532 -0
  44. package/.eslintignore +0 -15
  45. package/.gitattributes +0 -2
  46. package/.github/ISSUE_TEMPLATE/compiler-errors-for-invalid-state-declarations.md +0 -25
  47. package/.github/ISSUE_TEMPLATE/new_ticket.yaml +0 -34
  48. package/.github/pull_request_template.md +0 -15
  49. package/.github/workflows/discord-changelog.yml +0 -141
  50. package/.github/workflows/discord-notify.yml +0 -242
  51. package/.github/workflows/discord-version.yml +0 -195
  52. package/.prettierignore +0 -13
  53. package/.prettierrc +0 -21
  54. package/.zen.d.ts +0 -15
  55. package/app/components/Button.zen +0 -46
  56. package/app/components/Link.zen +0 -11
  57. package/app/favicon.ico +0 -0
  58. package/app/layouts/Main.zen +0 -59
  59. package/app/pages/about.zen +0 -23
  60. package/app/pages/blog/[id].zen +0 -53
  61. package/app/pages/blog/index.zen +0 -32
  62. package/app/pages/dynamic-dx.zen +0 -712
  63. package/app/pages/dynamic-primitives.zen +0 -453
  64. package/app/pages/index.zen +0 -154
  65. package/app/pages/navigation-demo.zen +0 -229
  66. package/app/pages/posts/[...slug].zen +0 -61
  67. package/app/pages/primitives-demo.zen +0 -273
  68. package/assets/logos/0E3B5DDD-605C-4839-BB2E-DFCA8ADC9604.PNG +0 -0
  69. package/assets/logos/760971E5-79A1-44F9-90B9-925DF30F4278.PNG +0 -0
  70. package/assets/logos/8A06ED80-9ED2-4689-BCBD-13B2E95EE8E4.JPG +0 -0
  71. package/assets/logos/C691FF58-ED13-4E8D-B6A3-02E835849340.PNG +0 -0
  72. package/assets/logos/C691FF58-ED13-4E8D-B6A3-02E835849340.svg +0 -601
  73. package/assets/logos/README.md +0 -54
  74. package/assets/logos/zen.icns +0 -0
  75. package/bun.lock +0 -39
  76. package/compiler/legacy/binding.ts +0 -254
  77. package/compiler/legacy/bindings.ts +0 -338
  78. package/compiler/legacy/component-process.ts +0 -1208
  79. package/compiler/legacy/component.ts +0 -301
  80. package/compiler/legacy/event.ts +0 -50
  81. package/compiler/legacy/expression.ts +0 -1149
  82. package/compiler/legacy/mutation.ts +0 -280
  83. package/compiler/legacy/parse.ts +0 -299
  84. package/compiler/legacy/split.ts +0 -608
  85. package/compiler/legacy/types.ts +0 -32
  86. package/docs/COMMENTS.md +0 -111
  87. package/docs/COMMITS.md +0 -36
  88. package/docs/CONTRIBUTING.md +0 -116
  89. package/docs/STYLEGUIDE.md +0 -62
  90. package/scripts/webhook-proxy.ts +0 -213
package/package.json CHANGED
@@ -1,10 +1,28 @@
1
1
  {
2
2
  "name": "@zenithbuild/core",
3
- "version": "0.1.0",
3
+ "version": "0.3.1",
4
4
  "description": "Core library for the Zenith framework",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "./index.ts",
8
+ "bin": {
9
+ "zenith": "./dist/zenith.js",
10
+ "zenith-dev": "./dist/zen-dev.js",
11
+ "zen-dev": "./dist/zen-dev.js",
12
+ "zen-build": "./dist/zen-build.js",
13
+ "zen-preview": "./dist/zen-preview.js"
14
+ },
15
+ "files": [
16
+ "bin",
17
+ "cli",
18
+ "compiler",
19
+ "core",
20
+ "router",
21
+ "runtime",
22
+ "dist",
23
+ "index.ts",
24
+ "tsconfig.json"
25
+ ],
8
26
  "exports": {
9
27
  ".": "./index.ts",
10
28
  "./compiler": "./compiler/index.ts",
@@ -26,12 +44,14 @@
26
44
  "dev": "bun dev",
27
45
  "build": "bun build",
28
46
  "start": "bun run build && bun run dev",
47
+ "build:cli": "bun build bin/zenith.ts bin/zen-dev.ts bin/zen-build.ts bin/zen-preview.ts --outdir dist --target bun --bundle && for f in dist/*.js; do echo '#!/usr/bin/env bun' | cat - \"$f\" > \"$f.tmp\" && mv \"$f.tmp\" \"$f\" && chmod +x \"$f\"; done",
29
48
  "format": "prettier --write \"**/*.ts\"",
30
49
  "format:check": "prettier --check \"**/*.ts\""
31
50
  },
32
51
  "private": false,
33
52
  "devDependencies": {
34
53
  "@types/bun": "latest",
54
+ "@types/node": "latest",
35
55
  "prettier": "^3.7.4"
36
56
  },
37
57
  "peerDependencies": {
@@ -41,4 +61,4 @@
41
61
  "@types/parse5": "^7.0.0",
42
62
  "parse5": "^8.0.0"
43
63
  }
44
- }
64
+ }
@@ -0,0 +1,416 @@
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
+ /**
16
+ * Generate the complete client runtime bundle
17
+ * This is served as an external JS file, not inlined
18
+ */
19
+ export function generateBundleJS(): string {
20
+ return `/*!
21
+ * Zenith Runtime v0.1.0
22
+ * Shared client-side runtime for hydration and reactivity
23
+ */
24
+ (function(global) {
25
+ 'use strict';
26
+
27
+ // ============================================
28
+ // Dependency Tracking System
29
+ // ============================================
30
+
31
+ let currentEffect = null;
32
+ const effectStack = [];
33
+ let batchDepth = 0;
34
+ const pendingEffects = new Set();
35
+
36
+ function pushContext(effect) {
37
+ effectStack.push(currentEffect);
38
+ currentEffect = effect;
39
+ }
40
+
41
+ function popContext() {
42
+ currentEffect = effectStack.pop() || null;
43
+ }
44
+
45
+ function trackDependency(subscribers) {
46
+ if (currentEffect) {
47
+ subscribers.add(currentEffect);
48
+ currentEffect.dependencies.add(subscribers);
49
+ }
50
+ }
51
+
52
+ function notifySubscribers(subscribers) {
53
+ const effects = [...subscribers];
54
+ for (const effect of effects) {
55
+ if (batchDepth > 0) {
56
+ pendingEffects.add(effect);
57
+ } else {
58
+ effect.run();
59
+ }
60
+ }
61
+ }
62
+
63
+ function cleanupEffect(effect) {
64
+ for (const deps of effect.dependencies) {
65
+ deps.delete(effect);
66
+ }
67
+ effect.dependencies.clear();
68
+ }
69
+
70
+ // ============================================
71
+ // zenSignal - Atomic reactive value
72
+ // ============================================
73
+
74
+ function zenSignal(initialValue) {
75
+ let value = initialValue;
76
+ const subscribers = new Set();
77
+
78
+ function signal(newValue) {
79
+ if (arguments.length === 0) {
80
+ trackDependency(subscribers);
81
+ return value;
82
+ }
83
+ if (newValue !== value) {
84
+ value = newValue;
85
+ notifySubscribers(subscribers);
86
+ }
87
+ return value;
88
+ }
89
+
90
+ return signal;
91
+ }
92
+
93
+ // ============================================
94
+ // zenState - Deep reactive object with Proxy
95
+ // ============================================
96
+
97
+ function zenState(initialObj) {
98
+ const subscribers = new Map();
99
+
100
+ function getSubscribers(path) {
101
+ if (!subscribers.has(path)) {
102
+ subscribers.set(path, new Set());
103
+ }
104
+ return subscribers.get(path);
105
+ }
106
+
107
+ function createProxy(obj, path) {
108
+ path = path || '';
109
+ if (typeof obj !== 'object' || obj === null) return obj;
110
+
111
+ return new Proxy(obj, {
112
+ get: function(target, prop) {
113
+ const propPath = path ? path + '.' + String(prop) : String(prop);
114
+ trackDependency(getSubscribers(propPath));
115
+ const value = target[prop];
116
+ if (typeof value === 'object' && value !== null) {
117
+ return createProxy(value, propPath);
118
+ }
119
+ return value;
120
+ },
121
+ set: function(target, prop, value) {
122
+ const propPath = path ? path + '.' + String(prop) : String(prop);
123
+ target[prop] = value;
124
+ notifySubscribers(getSubscribers(propPath));
125
+ if (path) {
126
+ notifySubscribers(getSubscribers(path));
127
+ }
128
+ return true;
129
+ }
130
+ });
131
+ }
132
+
133
+ return createProxy(initialObj);
134
+ }
135
+
136
+ // ============================================
137
+ // zenEffect - Auto-tracked side effect
138
+ // ============================================
139
+
140
+ function zenEffect(fn) {
141
+ const effect = {
142
+ fn: fn,
143
+ dependencies: new Set(),
144
+ run: function() {
145
+ cleanupEffect(this);
146
+ pushContext(this);
147
+ try {
148
+ this.fn();
149
+ } finally {
150
+ popContext();
151
+ }
152
+ },
153
+ dispose: function() {
154
+ cleanupEffect(this);
155
+ }
156
+ };
157
+
158
+ effect.run();
159
+ return function() { effect.dispose(); };
160
+ }
161
+
162
+ // ============================================
163
+ // zenMemo - Cached computed value
164
+ // ============================================
165
+
166
+ function zenMemo(fn) {
167
+ let cachedValue;
168
+ let dirty = true;
169
+ const subscribers = new Set();
170
+
171
+ const effect = {
172
+ dependencies: new Set(),
173
+ run: function() {
174
+ dirty = true;
175
+ notifySubscribers(subscribers);
176
+ }
177
+ };
178
+
179
+ function compute() {
180
+ if (dirty) {
181
+ cleanupEffect(effect);
182
+ pushContext(effect);
183
+ try {
184
+ cachedValue = fn();
185
+ dirty = false;
186
+ } finally {
187
+ popContext();
188
+ }
189
+ }
190
+ trackDependency(subscribers);
191
+ return cachedValue;
192
+ }
193
+
194
+ return compute;
195
+ }
196
+
197
+ // ============================================
198
+ // zenRef - Non-reactive mutable container
199
+ // ============================================
200
+
201
+ function zenRef(initialValue) {
202
+ return { current: initialValue !== undefined ? initialValue : null };
203
+ }
204
+
205
+ // ============================================
206
+ // zenBatch - Batch updates
207
+ // ============================================
208
+
209
+ function zenBatch(fn) {
210
+ batchDepth++;
211
+ try {
212
+ fn();
213
+ } finally {
214
+ batchDepth--;
215
+ if (batchDepth === 0) {
216
+ const effects = [...pendingEffects];
217
+ pendingEffects.clear();
218
+ for (const effect of effects) {
219
+ effect.run();
220
+ }
221
+ }
222
+ }
223
+ }
224
+
225
+ // ============================================
226
+ // zenUntrack - Read without tracking
227
+ // ============================================
228
+
229
+ function zenUntrack(fn) {
230
+ const prevEffect = currentEffect;
231
+ currentEffect = null;
232
+ try {
233
+ return fn();
234
+ } finally {
235
+ currentEffect = prevEffect;
236
+ }
237
+ }
238
+
239
+ // ============================================
240
+ // Lifecycle Hooks
241
+ // ============================================
242
+
243
+ const mountCallbacks = [];
244
+ const unmountCallbacks = [];
245
+ let isMounted = false;
246
+
247
+ function zenOnMount(fn) {
248
+ if (isMounted) {
249
+ const cleanup = fn();
250
+ if (typeof cleanup === 'function') {
251
+ unmountCallbacks.push(cleanup);
252
+ }
253
+ } else {
254
+ mountCallbacks.push(fn);
255
+ }
256
+ }
257
+
258
+ function zenOnUnmount(fn) {
259
+ unmountCallbacks.push(fn);
260
+ }
261
+
262
+ function triggerMount() {
263
+ isMounted = true;
264
+ for (let i = 0; i < mountCallbacks.length; i++) {
265
+ try {
266
+ const cleanup = mountCallbacks[i]();
267
+ if (typeof cleanup === 'function') {
268
+ unmountCallbacks.push(cleanup);
269
+ }
270
+ } catch(e) {
271
+ console.error('[Zenith] Mount error:', e);
272
+ }
273
+ }
274
+ mountCallbacks.length = 0;
275
+ }
276
+
277
+ function triggerUnmount() {
278
+ isMounted = false;
279
+ for (let i = 0; i < unmountCallbacks.length; i++) {
280
+ try { unmountCallbacks[i](); } catch(e) { console.error('[Zenith] Unmount error:', e); }
281
+ }
282
+ unmountCallbacks.length = 0;
283
+ }
284
+
285
+ // ============================================
286
+ // Expression Registry & Hydration
287
+ // ============================================
288
+
289
+ const expressionRegistry = new Map();
290
+
291
+ function registerExpression(id, fn) {
292
+ expressionRegistry.set(id, fn);
293
+ }
294
+
295
+ function getExpression(id) {
296
+ return expressionRegistry.get(id);
297
+ }
298
+
299
+ /**
300
+ * Hydrate a page with reactive bindings
301
+ * Called after page HTML is in DOM
302
+ */
303
+ function zenithHydrate(pageState, container) {
304
+ container = container || document;
305
+
306
+ // Find all data-zen-bind elements
307
+ const bindings = container.querySelectorAll('[data-zen-bind]');
308
+
309
+ bindings.forEach(function(el) {
310
+ const bindType = el.getAttribute('data-zen-bind');
311
+ const exprId = el.getAttribute('data-zen-expr');
312
+
313
+ if (bindType === 'text' && exprId) {
314
+ const expr = getExpression(exprId);
315
+ if (expr) {
316
+ zenEffect(function() {
317
+ el.textContent = expr(pageState);
318
+ });
319
+ }
320
+ } else if (bindType === 'attr') {
321
+ const attrName = el.getAttribute('data-zen-attr');
322
+ const expr = getExpression(exprId);
323
+ if (expr && attrName) {
324
+ zenEffect(function() {
325
+ el.setAttribute(attrName, expr(pageState));
326
+ });
327
+ }
328
+ }
329
+ });
330
+
331
+ // Wire up event handlers
332
+ const handlers = container.querySelectorAll('[data-zen-event]');
333
+ handlers.forEach(function(el) {
334
+ const eventData = el.getAttribute('data-zen-event');
335
+ if (eventData) {
336
+ const parts = eventData.split(':');
337
+ const eventType = parts[0];
338
+ const handlerName = parts[1];
339
+ if (handlerName && global[handlerName]) {
340
+ el.addEventListener(eventType, global[handlerName]);
341
+ }
342
+ }
343
+ });
344
+
345
+ // Trigger mount
346
+ triggerMount();
347
+ }
348
+
349
+ // ============================================
350
+ // Export to window.__zenith
351
+ // ============================================
352
+
353
+ global.__zenith = {
354
+ // Reactivity primitives
355
+ signal: zenSignal,
356
+ state: zenState,
357
+ effect: zenEffect,
358
+ memo: zenMemo,
359
+ ref: zenRef,
360
+ batch: zenBatch,
361
+ untrack: zenUntrack,
362
+ // Lifecycle
363
+ onMount: zenOnMount,
364
+ onUnmount: zenOnUnmount,
365
+ // Internal hooks
366
+ triggerMount: triggerMount,
367
+ triggerUnmount: triggerUnmount,
368
+ // Hydration
369
+ hydrate: zenithHydrate,
370
+ registerExpression: registerExpression,
371
+ getExpression: getExpression
372
+ };
373
+
374
+ // Expose with zen* prefix for direct usage
375
+ global.zenSignal = zenSignal;
376
+ global.zenState = zenState;
377
+ global.zenEffect = zenEffect;
378
+ global.zenMemo = zenMemo;
379
+ global.zenRef = zenRef;
380
+ global.zenBatch = zenBatch;
381
+ global.zenUntrack = zenUntrack;
382
+ global.zenOnMount = zenOnMount;
383
+ global.zenOnUnmount = zenOnUnmount;
384
+ global.zenithHydrate = zenithHydrate;
385
+
386
+ // Clean aliases
387
+ global.signal = zenSignal;
388
+ global.state = zenState;
389
+ global.effect = zenEffect;
390
+ global.memo = zenMemo;
391
+ global.ref = zenRef;
392
+ global.batch = zenBatch;
393
+ global.untrack = zenUntrack;
394
+ global.onMount = zenOnMount;
395
+ global.onUnmount = zenOnUnmount;
396
+
397
+ })(typeof window !== 'undefined' ? window : this);
398
+ `
399
+ }
400
+
401
+ /**
402
+ * Generate a minified version of the bundle
403
+ * For production builds
404
+ */
405
+ export function generateMinifiedBundleJS(): string {
406
+ // For now, return non-minified
407
+ // TODO: Add minification via terser or similar
408
+ return generateBundleJS()
409
+ }
410
+
411
+ /**
412
+ * Get bundle version for cache busting
413
+ */
414
+ export function getBundleVersion(): string {
415
+ return '0.1.0'
416
+ }