@zenithbuild/core 1.2.1 → 1.2.3

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 (82) hide show
  1. package/README.md +20 -19
  2. package/cli/commands/add.ts +2 -2
  3. package/cli/commands/build.ts +2 -3
  4. package/cli/commands/dev.ts +93 -73
  5. package/cli/commands/index.ts +1 -1
  6. package/cli/commands/preview.ts +1 -1
  7. package/cli/commands/remove.ts +2 -2
  8. package/cli/index.ts +1 -1
  9. package/cli/main.ts +1 -1
  10. package/cli/utils/logger.ts +1 -1
  11. package/cli/utils/plugin-manager.ts +1 -1
  12. package/cli/utils/project.ts +4 -4
  13. package/core/components/ErrorPage.zen +218 -0
  14. package/core/components/index.ts +15 -0
  15. package/core/config.ts +1 -0
  16. package/core/index.ts +29 -0
  17. package/dist/compiler-native-frej59m4.node +0 -0
  18. package/dist/core/compiler-native-frej59m4.node +0 -0
  19. package/dist/core/index.js +6293 -0
  20. package/dist/runtime/lifecycle/index.js +1 -0
  21. package/dist/runtime/reactivity/index.js +1 -0
  22. package/dist/zen-build.js +1 -20118
  23. package/dist/zen-dev.js +1 -20118
  24. package/dist/zen-preview.js +1 -20118
  25. package/dist/zenith.js +1 -20118
  26. package/package.json +12 -21
  27. package/compiler/README.md +0 -380
  28. package/compiler/build-analyzer.ts +0 -122
  29. package/compiler/css/index.ts +0 -317
  30. package/compiler/discovery/componentDiscovery.ts +0 -242
  31. package/compiler/discovery/layouts.ts +0 -70
  32. package/compiler/errors/compilerError.ts +0 -56
  33. package/compiler/finalize/finalizeOutput.ts +0 -192
  34. package/compiler/finalize/generateFinalBundle.ts +0 -82
  35. package/compiler/index.ts +0 -83
  36. package/compiler/ir/types.ts +0 -174
  37. package/compiler/output/types.ts +0 -48
  38. package/compiler/parse/detectMapExpressions.ts +0 -102
  39. package/compiler/parse/importTypes.ts +0 -78
  40. package/compiler/parse/parseImports.ts +0 -309
  41. package/compiler/parse/parseScript.ts +0 -46
  42. package/compiler/parse/parseTemplate.ts +0 -628
  43. package/compiler/parse/parseZenFile.ts +0 -66
  44. package/compiler/parse/scriptAnalysis.ts +0 -91
  45. package/compiler/parse/trackLoopContext.ts +0 -82
  46. package/compiler/runtime/dataExposure.ts +0 -332
  47. package/compiler/runtime/generateDOM.ts +0 -255
  48. package/compiler/runtime/generateHydrationBundle.ts +0 -407
  49. package/compiler/runtime/hydration.ts +0 -309
  50. package/compiler/runtime/navigation.ts +0 -432
  51. package/compiler/runtime/thinRuntime.ts +0 -160
  52. package/compiler/runtime/transformIR.ts +0 -406
  53. package/compiler/runtime/wrapExpression.ts +0 -114
  54. package/compiler/runtime/wrapExpressionWithLoop.ts +0 -97
  55. package/compiler/spa-build.ts +0 -917
  56. package/compiler/ssg-build.ts +0 -486
  57. package/compiler/test/component-stacking.test.ts +0 -365
  58. package/compiler/test/validate-test.ts +0 -104
  59. package/compiler/transform/classifyExpression.ts +0 -444
  60. package/compiler/transform/componentResolver.ts +0 -350
  61. package/compiler/transform/componentScriptTransformer.ts +0 -303
  62. package/compiler/transform/expressionTransformer.ts +0 -385
  63. package/compiler/transform/fragmentLowering.ts +0 -692
  64. package/compiler/transform/generateBindings.ts +0 -68
  65. package/compiler/transform/generateHTML.ts +0 -28
  66. package/compiler/transform/layoutProcessor.ts +0 -132
  67. package/compiler/transform/slotResolver.ts +0 -292
  68. package/compiler/transform/transformNode.ts +0 -240
  69. package/compiler/transform/transformTemplate.ts +0 -38
  70. package/compiler/validate/invariants.ts +0 -292
  71. package/compiler/validate/validateExpressions.ts +0 -168
  72. package/core/config/index.ts +0 -18
  73. package/core/config/loader.ts +0 -69
  74. package/core/config/types.ts +0 -119
  75. package/core/plugins/bridge.ts +0 -193
  76. package/core/plugins/index.ts +0 -7
  77. package/core/plugins/registry.ts +0 -126
  78. package/dist/cli.js +0 -11675
  79. package/runtime/build.ts +0 -17
  80. package/runtime/bundle-generator.ts +0 -1266
  81. package/runtime/client-runtime.ts +0 -891
  82. package/runtime/serve.ts +0 -93
@@ -1,365 +0,0 @@
1
- /**
2
- * Component Stacking Test
3
- *
4
- * Tests that multiple sibling components and multiple instances
5
- * of the same component render correctly.
6
- */
7
-
8
- import { compileZenSource } from '../index'
9
- import { discoverComponents, type ComponentMetadata } from '../discovery/componentDiscovery'
10
- import { resolveComponentsInIR } from '../transform/componentResolver'
11
- import { parseTemplate } from '../parse/parseTemplate'
12
- import * as fs from 'fs'
13
- import * as path from 'path'
14
-
15
- // Test 1: Multiple sibling components
16
- async function testMultipleSiblingComponents() {
17
- console.log('\n=== Test 1: Multiple Sibling Components ===\n')
18
-
19
- // Create mock components
20
- const mockComponents = new Map<string, ComponentMetadata>()
21
-
22
- mockComponents.set('Header', {
23
- name: 'Header',
24
- path: '/mock/Header.zen',
25
- template: '<header class="test-header">Header Content</header>',
26
- nodes: [{
27
- type: 'element',
28
- tag: 'header',
29
- attributes: [{ name: 'class', value: 'test-header', location: { line: 1, column: 1 } }],
30
- children: [{ type: 'text', value: 'Header Content', location: { line: 1, column: 1 } }],
31
- location: { line: 1, column: 1 }
32
- }],
33
- slots: [],
34
- props: [],
35
- styles: [],
36
- script: null,
37
- scriptAttributes: null,
38
- hasScript: false,
39
- hasStyles: false
40
- })
41
-
42
- mockComponents.set('Hero', {
43
- name: 'Hero',
44
- path: '/mock/Hero.zen',
45
- template: '<section class="test-hero">Hero Content</section>',
46
- nodes: [{
47
- type: 'element',
48
- tag: 'section',
49
- attributes: [{ name: 'class', value: 'test-hero', location: { line: 1, column: 1 } }],
50
- children: [{ type: 'text', value: 'Hero Content', location: { line: 1, column: 1 } }],
51
- location: { line: 1, column: 1 }
52
- }],
53
- slots: [],
54
- props: [],
55
- styles: [],
56
- script: null,
57
- scriptAttributes: null,
58
- hasScript: false,
59
- hasStyles: false
60
- })
61
-
62
- mockComponents.set('Footer', {
63
- name: 'Footer',
64
- path: '/mock/Footer.zen',
65
- template: '<footer class="test-footer">Footer Content</footer>',
66
- nodes: [{
67
- type: 'element',
68
- tag: 'footer',
69
- attributes: [{ name: 'class', value: 'test-footer', location: { line: 1, column: 1 } }],
70
- children: [{ type: 'text', value: 'Footer Content', location: { line: 1, column: 1 } }],
71
- location: { line: 1, column: 1 }
72
- }],
73
- slots: [],
74
- props: [],
75
- styles: [],
76
- script: null,
77
- scriptAttributes: null,
78
- hasScript: false,
79
- hasStyles: false
80
- })
81
-
82
- // Test source with multiple sibling components
83
- const testSource = `
84
- <script setup="ts">
85
- </script>
86
- <div class="page">
87
- <Header />
88
- <Hero />
89
- <Footer />
90
- </div>
91
- `
92
-
93
- // Parse the template
94
- const template = parseTemplate(testSource, 'test.zen')
95
-
96
- console.log('Parsed nodes:', JSON.stringify(template.nodes, null, 2))
97
- console.log('\nComponent nodes found:')
98
-
99
- // Find all component nodes
100
- function findComponents(nodes: any[], depth = 0): void {
101
- for (const node of nodes) {
102
- if (node.type === 'component') {
103
- console.log(`${' '.repeat(depth)}Component: ${node.name}`)
104
- } else if (node.type === 'element') {
105
- console.log(`${' '.repeat(depth)}Element: <${node.tag}>`)
106
- if (node.children) {
107
- findComponents(node.children, depth + 1)
108
- }
109
- }
110
- }
111
- }
112
-
113
- findComponents(template.nodes)
114
-
115
- // Create IR
116
- const ir = {
117
- filePath: 'test.zen',
118
- template,
119
- script: { raw: '', attributes: {} },
120
- styles: []
121
- }
122
-
123
- // Resolve components
124
- const resolvedIR = resolveComponentsInIR(ir, mockComponents)
125
-
126
- console.log('\nResolved nodes:', JSON.stringify(resolvedIR.template.nodes, null, 2))
127
-
128
- // Count how many test-* classes appear in the resolved HTML
129
- const jsonStr = JSON.stringify(resolvedIR.template.nodes)
130
- const countHeaders = (jsonStr.match(/"value":"test-header"/g) || []).length
131
- const countHeros = (jsonStr.match(/"value":"test-hero"/g) || []).length
132
- const countFooters = (jsonStr.match(/"value":"test-footer"/g) || []).length
133
-
134
- console.log(`\nResults:`)
135
- console.log(` Headers: ${countHeaders} (expected: 1)`)
136
- console.log(` Heros: ${countHeros} (expected: 1)`)
137
- console.log(` Footers: ${countFooters} (expected: 1)`)
138
-
139
- const passed = countHeaders === 1 && countHeros === 1 && countFooters === 1
140
- console.log(`\n${passed ? '✅ PASSED' : '❌ FAILED'}: Multiple sibling components`)
141
-
142
- return passed
143
- }
144
-
145
- // Test 2: Multiple instances of the same component
146
- async function testMultipleInstances() {
147
- console.log('\n=== Test 2: Multiple Instances of Same Component ===\n')
148
-
149
- const mockComponents = new Map<string, ComponentMetadata>()
150
-
151
- mockComponents.set('Card', {
152
- name: 'Card',
153
- path: '/mock/Card.zen',
154
- template: '<div class="card">Card Content</div>',
155
- nodes: [{
156
- type: 'element',
157
- tag: 'div',
158
- attributes: [{ name: 'class', value: 'card', location: { line: 1, column: 1 } }],
159
- children: [{ type: 'text', value: 'Card Content', location: { line: 1, column: 1 } }],
160
- location: { line: 1, column: 1 }
161
- }],
162
- slots: [],
163
- props: [],
164
- styles: [],
165
- script: null,
166
- scriptAttributes: null,
167
- hasScript: false,
168
- hasStyles: false
169
- })
170
-
171
- const testSource = `
172
- <script setup="ts">
173
- </script>
174
- <div class="grid">
175
- <Card />
176
- <Card />
177
- <Card />
178
- </div>
179
- `
180
-
181
- const template = parseTemplate(testSource, 'test.zen')
182
-
183
- console.log('Component nodes found:')
184
-
185
- function countComponents(nodes: any[]): number {
186
- let count = 0
187
- for (const node of nodes) {
188
- if (node.type === 'component') {
189
- console.log(` Found component: ${node.name}`)
190
- count++
191
- } else if (node.type === 'element' && node.children) {
192
- count += countComponents(node.children)
193
- }
194
- }
195
- return count
196
- }
197
-
198
- const componentCount = countComponents(template.nodes)
199
- console.log(`Total component nodes before resolution: ${componentCount}`)
200
-
201
- const ir = {
202
- filePath: 'test.zen',
203
- template,
204
- script: { raw: '', attributes: {} },
205
- styles: []
206
- }
207
-
208
- const resolvedIR = resolveComponentsInIR(ir, mockComponents)
209
-
210
- // Count card divs in resolved output - search for the attribute value
211
- const jsonStr = JSON.stringify(resolvedIR.template.nodes)
212
- const cardCount = (jsonStr.match(/"value":"card"/g) || []).length
213
-
214
- console.log(`\nResolved JSON (first 500 chars): ${jsonStr.substring(0, 500)}...`)
215
- console.log(`\nCard divs in resolved output: ${cardCount} (expected: 3)`)
216
-
217
- const passed = cardCount === 3
218
- console.log(`\n${passed ? '✅ PASSED' : '❌ FAILED'}: Multiple instances of same component`)
219
-
220
- return passed
221
- }
222
-
223
- // Test 3: Nested components
224
- async function testNestedComponents() {
225
- console.log('\n=== Test 3: Nested Components ===\n')
226
-
227
- const mockComponents = new Map<string, ComponentMetadata>()
228
-
229
- mockComponents.set('Outer', {
230
- name: 'Outer',
231
- path: '/mock/Outer.zen',
232
- template: '<div class="outer"><slot /></div>',
233
- nodes: [{
234
- type: 'element',
235
- tag: 'div',
236
- attributes: [{ name: 'class', value: 'outer', location: { line: 1, column: 1 } }],
237
- children: [{
238
- type: 'element',
239
- tag: 'slot',
240
- attributes: [],
241
- children: [],
242
- location: { line: 1, column: 1 }
243
- }],
244
- location: { line: 1, column: 1 }
245
- }],
246
- slots: [{ name: null, location: { line: 1, column: 1 } }],
247
- props: [],
248
- styles: [],
249
- script: null,
250
- scriptAttributes: null,
251
- hasScript: false,
252
- hasStyles: false
253
- })
254
-
255
- mockComponents.set('Inner', {
256
- name: 'Inner',
257
- path: '/mock/Inner.zen',
258
- template: '<span class="inner">Inner Content</span>',
259
- nodes: [{
260
- type: 'element',
261
- tag: 'span',
262
- attributes: [{ name: 'class', value: 'inner', location: { line: 1, column: 1 } }],
263
- children: [{ type: 'text', value: 'Inner Content', location: { line: 1, column: 1 } }],
264
- location: { line: 1, column: 1 }
265
- }],
266
- slots: [],
267
- props: [],
268
- styles: [],
269
- script: null,
270
- scriptAttributes: null,
271
- hasScript: false,
272
- hasStyles: false
273
- })
274
-
275
- const testSource = `
276
- <script setup="ts">
277
- </script>
278
- <Outer>
279
- <Inner />
280
- </Outer>
281
- `
282
-
283
- const template = parseTemplate(testSource, 'test.zen')
284
-
285
- const ir = {
286
- filePath: 'test.zen',
287
- template,
288
- script: { raw: '', attributes: {} },
289
- styles: []
290
- }
291
-
292
- const resolvedIR = resolveComponentsInIR(ir, mockComponents)
293
-
294
- const jsonStr = JSON.stringify(resolvedIR.template.nodes)
295
- const hasOuter = jsonStr.includes('"value":"outer"')
296
- const hasInner = jsonStr.includes('"value":"inner"')
297
-
298
- console.log(`Resolved JSON (first 500 chars): ${jsonStr.substring(0, 500)}...`)
299
- console.log(`Outer div present: ${hasOuter}`)
300
- console.log(`Inner span present: ${hasInner}`)
301
-
302
- const passed = hasOuter && hasInner
303
- console.log(`\n${passed ? '✅ PASSED' : '❌ FAILED'}: Nested components`)
304
-
305
- return passed
306
- }
307
-
308
- // Test 4: Auto-import naming (filename-based)
309
- async function testAutoImportNaming() {
310
- console.log('\n=== Test 4: Auto-Import Naming ===\n')
311
-
312
- // Test the naming algorithm directly
313
- // With the new convention, component name = filename (subdirectories are ignored)
314
- const testCases = [
315
- { input: 'components/Header.zen', expected: 'Header' },
316
- { input: 'components/globals/Header.zen', expected: 'Header' }, // Filename only!
317
- { input: 'components/ui/buttons/Primary.zen', expected: 'Primary' },
318
- { input: 'components/sections/HeroSection.zen', expected: 'HeroSection' },
319
- { input: 'components/ui-kit/Button.zen', expected: 'Button' },
320
- ]
321
-
322
- let passed = true
323
-
324
- for (const tc of testCases) {
325
- // Component name is just the filename without .zen extension
326
- const result = path.basename(tc.input, '.zen')
327
-
328
- const match = result === tc.expected
329
- console.log(` ${match ? '✓' : '✗'} "${tc.input}" → "${result}" (expected: "${tc.expected}")`)
330
-
331
- if (!match) passed = false
332
- }
333
-
334
- console.log(`\n${passed ? '✅ PASSED' : '❌ FAILED'}: Auto-import naming`)
335
-
336
- return passed
337
- }
338
-
339
- // Run all tests
340
- async function runTests() {
341
- console.log('╔════════════════════════════════════════════╗')
342
- console.log('║ Component Stacking Tests ║')
343
- console.log('╚════════════════════════════════════════════╝')
344
-
345
- const results = []
346
-
347
- results.push(await testMultipleSiblingComponents())
348
- results.push(await testMultipleInstances())
349
- results.push(await testNestedComponents())
350
- results.push(await testAutoImportNaming())
351
-
352
- console.log('\n════════════════════════════════════════════')
353
- console.log('Summary:')
354
- console.log(` Total: ${results.length}`)
355
- console.log(` Passed: ${results.filter(r => r).length}`)
356
- console.log(` Failed: ${results.filter(r => !r).length}`)
357
- console.log('════════════════════════════════════════════\n')
358
-
359
- process.exit(results.every(r => r) ? 0 : 1)
360
- }
361
-
362
- runTests().catch(err => {
363
- console.error('Test error:', err)
364
- process.exit(1)
365
- })
@@ -1,104 +0,0 @@
1
- /**
2
- * Test Cases for Expression Validation
3
- *
4
- * Phase 8/9/10: Tests that invalid expressions fail the build
5
- */
6
-
7
- import { validateExpressions, validateExpressionsOrThrow } from '../validate/validateExpressions'
8
- import type { ExpressionIR } from '../ir/types'
9
-
10
- /**
11
- * Test valid expressions
12
- */
13
- function testValidExpressions() {
14
- const validExpressions: ExpressionIR[] = [
15
- {
16
- id: 'expr_0',
17
- code: 'user.name',
18
- location: { line: 10, column: 5 }
19
- },
20
- {
21
- id: 'expr_1',
22
- code: 'count + 1',
23
- location: { line: 11, column: 8 }
24
- },
25
- {
26
- id: 'expr_2',
27
- code: 'isActive ? "on" : "off"',
28
- location: { line: 12, column: 12 }
29
- }
30
- ]
31
-
32
- const result = validateExpressions(validExpressions, 'test.zen')
33
- console.assert(result.valid === true, 'Valid expressions should pass validation')
34
- console.assert(result.errors.length === 0, 'Valid expressions should have no errors')
35
- console.log('✅ Valid expressions test passed')
36
- }
37
-
38
- /**
39
- * Test invalid expressions
40
- */
41
- function testInvalidExpressions() {
42
- const invalidExpressions: ExpressionIR[] = [
43
- {
44
- id: 'expr_0',
45
- code: 'user.name}', // Mismatched brace
46
- location: { line: 10, column: 5 }
47
- }
48
- ]
49
-
50
- const result = validateExpressions(invalidExpressions, 'test.zen')
51
- console.assert(result.valid === false, 'Invalid expressions should fail validation')
52
- console.assert(result.errors.length > 0, 'Invalid expressions should have errors')
53
- console.log('✅ Invalid expressions test passed')
54
- }
55
-
56
- /**
57
- * Test unsafe code detection
58
- */
59
- function testUnsafeCode() {
60
- const unsafeExpressions: ExpressionIR[] = [
61
- {
62
- id: 'expr_0',
63
- code: 'eval("alert(1)")',
64
- location: { line: 10, column: 5 }
65
- }
66
- ]
67
-
68
- const result = validateExpressions(unsafeExpressions, 'test.zen')
69
- console.assert(result.valid === false, 'Unsafe code should fail validation')
70
- console.assert(result.errors.length > 0, 'Unsafe code should have errors')
71
- console.log('✅ Unsafe code detection test passed')
72
- }
73
-
74
- /**
75
- * Test validateExpressionsOrThrow
76
- */
77
- function testThrowOnInvalid() {
78
- const invalidExpressions: ExpressionIR[] = [
79
- {
80
- id: 'expr_0',
81
- code: 'user.name}', // Mismatched brace
82
- location: { line: 10, column: 5 }
83
- }
84
- ]
85
-
86
- try {
87
- validateExpressionsOrThrow(invalidExpressions, 'test.zen')
88
- console.assert(false, 'Should have thrown on invalid expressions')
89
- } catch (error) {
90
- console.assert(error instanceof Error, 'Should throw Error')
91
- console.log('✅ Throw on invalid expressions test passed')
92
- }
93
- }
94
-
95
- // Run tests
96
- if (require.main === module) {
97
- console.log('Running validation tests...')
98
- testValidExpressions()
99
- testInvalidExpressions()
100
- testUnsafeCode()
101
- testThrowOnInvalid()
102
- console.log('✅ All validation tests passed!')
103
- }
104
-