@zenithbuild/core 0.6.2 → 0.6.4

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 (112) hide show
  1. package/CORE_CONTRACT.md +145 -0
  2. package/README.md +14 -29
  3. package/bin/zenith.js +89 -0
  4. package/package.json +39 -56
  5. package/src/config.js +136 -0
  6. package/src/core-template.js +30 -0
  7. package/src/errors.js +54 -0
  8. package/src/guards.js +61 -0
  9. package/src/hash.js +52 -0
  10. package/src/index.js +26 -0
  11. package/src/ir/index.js +1 -0
  12. package/src/order.js +69 -0
  13. package/src/path.js +131 -0
  14. package/src/schema.js +28 -0
  15. package/src/version.js +67 -0
  16. package/bin/zen-build.ts +0 -2
  17. package/bin/zen-dev.ts +0 -2
  18. package/bin/zen-preview.ts +0 -2
  19. package/bin/zenith.ts +0 -2
  20. package/cli/commands/add.ts +0 -37
  21. package/cli/commands/build.ts +0 -37
  22. package/cli/commands/create.ts +0 -702
  23. package/cli/commands/dev.ts +0 -388
  24. package/cli/commands/index.ts +0 -112
  25. package/cli/commands/preview.ts +0 -62
  26. package/cli/commands/remove.ts +0 -33
  27. package/cli/index.ts +0 -10
  28. package/cli/main.ts +0 -101
  29. package/cli/utils/branding.ts +0 -178
  30. package/cli/utils/content.ts +0 -112
  31. package/cli/utils/logger.ts +0 -46
  32. package/cli/utils/plugin-manager.ts +0 -114
  33. package/cli/utils/project.ts +0 -77
  34. package/compiler/README.md +0 -380
  35. package/compiler/build-analyzer.ts +0 -122
  36. package/compiler/css/index.ts +0 -317
  37. package/compiler/discovery/componentDiscovery.ts +0 -178
  38. package/compiler/discovery/layouts.ts +0 -70
  39. package/compiler/errors/compilerError.ts +0 -56
  40. package/compiler/finalize/finalizeOutput.ts +0 -192
  41. package/compiler/finalize/generateFinalBundle.ts +0 -82
  42. package/compiler/index.ts +0 -83
  43. package/compiler/ir/types.ts +0 -174
  44. package/compiler/output/types.ts +0 -34
  45. package/compiler/parse/detectMapExpressions.ts +0 -102
  46. package/compiler/parse/importTypes.ts +0 -78
  47. package/compiler/parse/parseImports.ts +0 -309
  48. package/compiler/parse/parseScript.ts +0 -46
  49. package/compiler/parse/parseTemplate.ts +0 -599
  50. package/compiler/parse/parseZenFile.ts +0 -66
  51. package/compiler/parse/scriptAnalysis.ts +0 -91
  52. package/compiler/parse/trackLoopContext.ts +0 -82
  53. package/compiler/runtime/dataExposure.ts +0 -317
  54. package/compiler/runtime/generateDOM.ts +0 -246
  55. package/compiler/runtime/generateHydrationBundle.ts +0 -407
  56. package/compiler/runtime/hydration.ts +0 -309
  57. package/compiler/runtime/navigation.ts +0 -432
  58. package/compiler/runtime/thinRuntime.ts +0 -160
  59. package/compiler/runtime/transformIR.ts +0 -370
  60. package/compiler/runtime/wrapExpression.ts +0 -95
  61. package/compiler/runtime/wrapExpressionWithLoop.ts +0 -83
  62. package/compiler/spa-build.ts +0 -917
  63. package/compiler/ssg-build.ts +0 -422
  64. package/compiler/test/validate-test.ts +0 -104
  65. package/compiler/transform/classifyExpression.ts +0 -444
  66. package/compiler/transform/componentResolver.ts +0 -312
  67. package/compiler/transform/componentScriptTransformer.ts +0 -303
  68. package/compiler/transform/expressionTransformer.ts +0 -385
  69. package/compiler/transform/fragmentLowering.ts +0 -634
  70. package/compiler/transform/generateBindings.ts +0 -47
  71. package/compiler/transform/generateHTML.ts +0 -28
  72. package/compiler/transform/layoutProcessor.ts +0 -132
  73. package/compiler/transform/slotResolver.ts +0 -292
  74. package/compiler/transform/transformNode.ts +0 -126
  75. package/compiler/transform/transformTemplate.ts +0 -38
  76. package/compiler/validate/invariants.ts +0 -292
  77. package/compiler/validate/validateExpressions.ts +0 -168
  78. package/core/config/index.ts +0 -16
  79. package/core/config/loader.ts +0 -69
  80. package/core/config/types.ts +0 -89
  81. package/core/index.ts +0 -135
  82. package/core/lifecycle/index.ts +0 -49
  83. package/core/lifecycle/zen-mount.ts +0 -182
  84. package/core/lifecycle/zen-unmount.ts +0 -88
  85. package/core/plugins/index.ts +0 -7
  86. package/core/plugins/registry.ts +0 -81
  87. package/core/reactivity/index.ts +0 -54
  88. package/core/reactivity/tracking.ts +0 -167
  89. package/core/reactivity/zen-batch.ts +0 -57
  90. package/core/reactivity/zen-effect.ts +0 -139
  91. package/core/reactivity/zen-memo.ts +0 -146
  92. package/core/reactivity/zen-ref.ts +0 -52
  93. package/core/reactivity/zen-signal.ts +0 -121
  94. package/core/reactivity/zen-state.ts +0 -180
  95. package/core/reactivity/zen-untrack.ts +0 -44
  96. package/dist/cli.js +0 -11665
  97. package/dist/zen-build.js +0 -21172
  98. package/dist/zen-dev.js +0 -21172
  99. package/dist/zen-preview.js +0 -21172
  100. package/dist/zenith.js +0 -21172
  101. package/router/index.ts +0 -28
  102. package/router/manifest.ts +0 -314
  103. package/router/navigation/ZenLink.zen +0 -231
  104. package/router/navigation/index.ts +0 -78
  105. package/router/navigation/zen-link.ts +0 -584
  106. package/router/runtime.ts +0 -458
  107. package/router/types.ts +0 -168
  108. package/runtime/build.ts +0 -17
  109. package/runtime/bundle-generator.ts +0 -1247
  110. package/runtime/client-runtime.ts +0 -549
  111. package/runtime/serve.ts +0 -93
  112. package/tsconfig.json +0 -28
@@ -1,91 +0,0 @@
1
- /**
2
- * Script Analysis Utilities
3
- *
4
- * Extracts state and prop declarations from <script> blocks
5
- */
6
-
7
- export interface StateInfo {
8
- name: string
9
- value: string
10
- }
11
-
12
- /**
13
- * Extract state declarations: state name = value
14
- */
15
- export function extractStateDeclarations(script: string): Map<string, string> {
16
- const states = new Map<string, string>()
17
- const statePattern = /state\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=\s*([^;]+?)(?:\s*;|\s*$)/gm
18
- let match
19
-
20
- while ((match = statePattern.exec(script)) !== null) {
21
- if (match[1] && match[2]) {
22
- states.set(match[1], match[2].trim())
23
- }
24
- }
25
-
26
- return states
27
- }
28
-
29
- /**
30
- * Extract prop declarations: export let props: Props;
31
- */
32
- export function extractProps(script: string): string[] {
33
- const props: string[] = []
34
- const propPattern = /export\s+let\s+props(?:\s*:\s*([^;]+))?[ \t]*;?/g
35
- let match
36
-
37
- while ((match = propPattern.exec(script)) !== null) {
38
- if (!props.includes('props')) {
39
- props.push('props')
40
- }
41
- }
42
-
43
- return props
44
- }
45
-
46
- /**
47
- * Transform script by removing state and prop declarations
48
- * Also strips .zen imports (resolved at compile time) and other compile-time-only imports
49
- */
50
- export function transformStateDeclarations(script: string): string {
51
- let transformed = script
52
-
53
- // Remove state declarations (state count = 0)
54
- transformed = transformed.replace(/state\s+([a-zA-Z_$][a-zA-Z0-9_$]*)[ \t]*=[ \t]*([^;]+?)(?:[ \t]*;|\s*$)/gm, '')
55
-
56
- // Remove export let props (legacy)
57
- transformed = transformed.replace(/export\s+let\s+props(?:\s*:\s*([^;]+))?\s*;?[ \t]*/g, '')
58
-
59
- // Remove type/interface Props (carefully handling comments)
60
- // We search for the start of the word 'type' or 'interface' and match until the closing brace
61
- transformed = transformed.replace(/(?:type|interface)\s+Props\s*=?\s*\{[^}]*(?:\{[^}]*\}[^}]*)*\}[ \t]*;?/gs, '')
62
-
63
- // Remove zenith/runtime imports
64
- transformed = transformed.replace(/import\s+{[^}]+}\s+from\s+['"]zenith\/runtime['"]\s*;?[ \t]*/g, '')
65
-
66
- // Remove .zen file imports (resolved at compile time)
67
- // Matches: import Name from '.../file.zen'; or import Name from '.../file.zen'
68
- transformed = transformed.replace(/import\s+\w+\s+from\s+['"][^'"]*\.zen['"];?\s*/g, '')
69
-
70
- // Remove relative imports with destructuring (components are inlined)
71
- transformed = transformed.replace(/import\s+{[^}]*}\s+from\s+['"][^'"]+\.zen['"];?\s*/g, '')
72
-
73
- // Transform zenith:content imports to global lookups
74
- transformed = transformed.replace(
75
- /import\s*{\s*([^}]+)\s*}\s*from\s*['"]zenith:content['"]\s*;?/g,
76
- (_, imports) => `const { ${imports.trim()} } = window.__zenith;`
77
- )
78
-
79
- return transformed.trim()
80
- }
81
-
82
- /**
83
- * Inject props into a setup script as top-level variables
84
- */
85
- export function injectPropsIntoSetup(script: string, props: Record<string, any>): string {
86
- const propDeclarations = Object.entries(props)
87
- .map(([key, value]) => `const ${key} = ${typeof value === 'string' ? `'${value}'` : JSON.stringify(value)};`)
88
- .join('\n')
89
-
90
- return `${propDeclarations}\n\n${script}`
91
- }
@@ -1,82 +0,0 @@
1
- /**
2
- * Loop Context Tracking
3
- *
4
- * Phase 7: Utilities for tracking and propagating loop context through the parse tree
5
- */
6
-
7
- import type { LoopContext, ExpressionIR } from '../ir/types'
8
- import { detectMapExpression, referencesLoopVariable } from './detectMapExpressions'
9
-
10
- /**
11
- * Check if an expression should have loop context attached
12
- * Returns the loop context if the expression references loop variables
13
- */
14
- export function shouldAttachLoopContext(
15
- expr: ExpressionIR,
16
- parentLoopContext?: LoopContext
17
- ): LoopContext | undefined {
18
- if (!parentLoopContext) {
19
- return undefined
20
- }
21
-
22
- // Check if this expression references any loop variables
23
- if (referencesLoopVariable(expr.code, parentLoopContext.variables)) {
24
- return parentLoopContext
25
- }
26
-
27
- return undefined
28
- }
29
-
30
- /**
31
- * Merge loop contexts for nested loops
32
- * Inner loops inherit outer loop variables
33
- */
34
- export function mergeLoopContext(
35
- outer?: LoopContext,
36
- inner?: LoopContext
37
- ): LoopContext | undefined {
38
- if (!inner) {
39
- return outer
40
- }
41
-
42
- if (!outer) {
43
- return inner
44
- }
45
-
46
- // Merge variables: outer variables come first, then inner
47
- // This allows expressions to reference both outer and inner loop variables
48
- return {
49
- variables: [...outer.variables, ...inner.variables],
50
- mapSource: inner.mapSource || outer.mapSource
51
- }
52
- }
53
-
54
- /**
55
- * Detect if an expression is a map expression and extract its loop context
56
- */
57
- export function extractLoopContextFromExpression(expr: ExpressionIR): LoopContext | undefined {
58
- const mapInfo = detectMapExpression(expr)
59
-
60
- if (!mapInfo.isMap) {
61
- return undefined
62
- }
63
-
64
- // extractLoopVariables expects a MapExpressionInfo, not a string
65
- const variables: string[] = []
66
- if (mapInfo.itemVariable) {
67
- variables.push(mapInfo.itemVariable)
68
- }
69
- if (mapInfo.indexVariable) {
70
- variables.push(mapInfo.indexVariable)
71
- }
72
-
73
- if (variables.length === 0) {
74
- return undefined
75
- }
76
-
77
- return {
78
- variables,
79
- mapSource: mapInfo.arraySource
80
- }
81
- }
82
-
@@ -1,317 +0,0 @@
1
- /**
2
- * Explicit Data Exposure Analysis
3
- *
4
- * Phase 6: Analyzes expressions to detect data dependencies and ensure
5
- * all data references are explicit (loader, props, stores) rather than implicit globals
6
- */
7
-
8
- import type { ExpressionIR } from '../ir/types'
9
- import { CompilerError } from '../errors/compilerError'
10
- import { transformExpressionJSX } from '../transform/expressionTransformer'
11
-
12
- /**
13
- * Data dependency information for an expression
14
- */
15
- export interface ExpressionDataDependencies {
16
- expressionId: string
17
- usesLoaderData: boolean
18
- usesProps: boolean
19
- usesStores: boolean
20
- usesState: boolean
21
- loaderProperties: string[] // e.g., ['user', 'user.name']
22
- propNames: string[] // e.g., ['title', 'showWelcome']
23
- storeNames: string[] // e.g., ['cart', 'notifications']
24
- stateProperties: string[] // e.g., ['count', 'isLoading']
25
- }
26
-
27
- /**
28
- * Analyze an expression to detect its data dependencies
29
- *
30
- * This is a simple heuristic-based analyzer that looks for patterns like:
31
- * - user.name, user.email → loader data
32
- * - props.title, props.showWelcome → props
33
- * - stores.cart, stores.notifications → stores
34
- * - count, isLoading → state (top-level properties)
35
- */
36
- export function analyzeExpressionDependencies(
37
- expr: ExpressionIR,
38
- declaredLoaderProps: string[] = [],
39
- declaredProps: string[] = [],
40
- declaredStores: string[] = []
41
- ): ExpressionDataDependencies {
42
- const { id, code } = expr
43
-
44
- const dependencies: ExpressionDataDependencies = {
45
- expressionId: id,
46
- usesLoaderData: false,
47
- usesProps: false,
48
- usesStores: false,
49
- usesState: false,
50
- loaderProperties: [],
51
- propNames: [],
52
- storeNames: [],
53
- stateProperties: []
54
- }
55
-
56
- // Simple pattern matching (for Phase 6 - can be enhanced with proper AST parsing later)
57
-
58
- // Check for loader data references (loaderData.property or direct property access)
59
- // We assume properties not starting with props/stores/state are loader data
60
- const loaderPattern = /\b(loaderData\.(\w+(?:\.\w+)*)|(?<!props\.|stores\.|state\.)(\w+)\.(\w+))/g
61
- let match
62
-
63
- // Check for explicit loaderData references
64
- if (/loaderData\./.test(code)) {
65
- dependencies.usesLoaderData = true
66
- while ((match = loaderPattern.exec(code)) !== null) {
67
- if (match[1]?.startsWith('loaderData.')) {
68
- const propPath = match[1].replace('loaderData.', '')
69
- if (!dependencies.loaderProperties.includes(propPath)) {
70
- dependencies.loaderProperties.push(propPath)
71
- }
72
- }
73
- }
74
- }
75
-
76
- // Check for props references
77
- const propsPattern = /\bprops\.(\w+)(?:\.(\w+))*/g
78
- if (/props\./.test(code)) {
79
- dependencies.usesProps = true
80
- while ((match = propsPattern.exec(code)) !== null) {
81
- const propName = match[1]
82
- if (propName && !dependencies.propNames.includes(propName)) {
83
- dependencies.propNames.push(propName)
84
- }
85
- }
86
- }
87
-
88
- // Check for stores references
89
- const storesPattern = /\bstores\.(\w+)(?:\.(\w+))*/g
90
- if (/stores\./.test(code)) {
91
- dependencies.usesStores = true
92
- while ((match = storesPattern.exec(code)) !== null) {
93
- const storeName = match[1]
94
- if (storeName && !dependencies.storeNames.includes(storeName)) {
95
- dependencies.storeNames.push(storeName)
96
- }
97
- }
98
- }
99
-
100
- // Check for state references (top-level properties)
101
- // Simple identifiers that aren't part of props/stores/loaderData paths
102
- const identifierPattern = /\b([a-zA-Z_$][a-zA-Z0-9_$]*)\b/g
103
- const reserved = ['props', 'stores', 'loaderData', 'state', 'true', 'false', 'null', 'undefined', 'this', 'window']
104
-
105
- const identifiers = new Set<string>()
106
- while ((match = identifierPattern.exec(code)) !== null) {
107
- const ident = match[1]
108
- if (ident && !reserved.includes(ident) && !ident.includes('.')) {
109
- identifiers.add(ident)
110
- }
111
- }
112
-
113
- // If we have identifiers, check if they are props or state
114
- if (identifiers.size > 0) {
115
- const propIdents: string[] = []
116
- const stateIdents: string[] = []
117
-
118
- for (const ident of identifiers) {
119
- if (declaredProps.includes(ident)) {
120
- propIdents.push(ident)
121
- } else {
122
- stateIdents.push(ident)
123
- }
124
- }
125
-
126
- if (propIdents.length > 0) {
127
- dependencies.usesProps = true
128
- dependencies.propNames = [...new Set([...dependencies.propNames, ...propIdents])]
129
- }
130
-
131
- if (stateIdents.length > 0) {
132
- dependencies.usesState = true
133
- dependencies.stateProperties = Array.from(new Set([...dependencies.stateProperties, ...stateIdents]))
134
- }
135
- }
136
-
137
- return dependencies
138
- }
139
-
140
- /**
141
- * Validate that all referenced data exists
142
- */
143
- export function validateDataDependencies(
144
- dependencies: ExpressionDataDependencies,
145
- filePath: string,
146
- declaredLoaderProps: string[] = [],
147
- declaredProps: string[] = [],
148
- declaredStores: string[] = []
149
- ): void {
150
- const errors: CompilerError[] = []
151
-
152
- // Validate loader data properties
153
- if (dependencies.usesLoaderData && dependencies.loaderProperties.length > 0) {
154
- // For Phase 6, we'll allow any loader property (can be enhanced with type checking later)
155
- // Just warn if property path is suspicious
156
- for (const prop of dependencies.loaderProperties) {
157
- if (!/^[a-zA-Z_$][a-zA-Z0-9_$.]*$/.test(prop)) {
158
- errors.push(new CompilerError(
159
- `Invalid loader data property reference: ${prop}`,
160
- filePath,
161
- 0,
162
- 0
163
- ))
164
- }
165
- }
166
- }
167
-
168
- // Validate props
169
- if (dependencies.usesProps && dependencies.propNames.length > 0) {
170
- for (const propName of dependencies.propNames) {
171
- if (declaredProps.length > 0 && !declaredProps.includes(propName)) {
172
- // This is a warning, not an error - props might be passed at runtime
173
- console.warn(`[Zenith] Prop "${propName}" referenced but not declared in component`)
174
- }
175
- }
176
- }
177
-
178
- // Validate stores
179
- if (dependencies.usesStores && dependencies.storeNames.length > 0) {
180
- for (const storeName of dependencies.storeNames) {
181
- if (declaredStores.length > 0 && !declaredStores.includes(storeName)) {
182
- errors.push(new CompilerError(
183
- `Store "${storeName}" referenced but not imported or declared`,
184
- filePath,
185
- 0,
186
- 0
187
- ))
188
- }
189
- }
190
- }
191
-
192
- if (errors.length > 0) {
193
- throw errors[0] // Throw first error (can be enhanced to collect all)
194
- }
195
- }
196
-
197
- /**
198
- * Transform expression code to use explicit data arguments
199
- *
200
- * Converts patterns like:
201
- * - user.name → loaderData.user.name
202
- * - title → props.title (if declared as prop)
203
- * - cart.items → stores.cart.items
204
- */
205
- export function transformExpressionCode(
206
- code: string,
207
- dependencies: ExpressionDataDependencies,
208
- declaredProps: string[] = []
209
- ): string {
210
- let transformed = code
211
-
212
- // For Phase 6, we keep the code as-is but ensure expressions
213
- // receive the right arguments. The actual transformation happens
214
- // in the expression wrapper function signature.
215
-
216
- // However, if the code references properties directly (without loaderData/props/stores prefix),
217
- // we need to assume they're state properties (backwards compatibility)
218
-
219
- return transformed
220
- }
221
-
222
- /**
223
- * Generate expression wrapper with explicit data arguments
224
- */
225
- export function generateExplicitExpressionWrapper(
226
- expr: ExpressionIR,
227
- dependencies: ExpressionDataDependencies
228
- ): string {
229
- const { id, code } = expr
230
-
231
- // Build function signature based on dependencies
232
- const params: string[] = ['state']
233
-
234
- if (dependencies.usesLoaderData) {
235
- params.push('loaderData')
236
- }
237
- if (dependencies.usesProps) {
238
- params.push('props')
239
- }
240
- if (dependencies.usesStores) {
241
- params.push('stores')
242
- }
243
-
244
- const paramList = params.join(', ')
245
-
246
- // Build evaluation context
247
- const contextParts: string[] = []
248
-
249
- if (dependencies.usesLoaderData) {
250
- contextParts.push('loaderData')
251
- }
252
- if (dependencies.usesProps) {
253
- contextParts.push('props')
254
- }
255
- if (dependencies.usesStores) {
256
- contextParts.push('stores')
257
- }
258
- if (dependencies.usesState) {
259
- contextParts.push('state')
260
- }
261
-
262
- // Create merged context for 'with' statement
263
- const contextCode = contextParts.length > 0
264
- ? `const __ctx = Object.assign({}, ${contextParts.join(', ')});\n with (__ctx) {`
265
- : 'with (state) {'
266
-
267
- // Escape the code for use in a single-line comment (replace newlines with spaces)
268
- const commentCode = code.replace(/[\r\n]+/g, ' ').replace(/\s+/g, ' ').substring(0, 100)
269
-
270
- // JSON.stringify the code for error messages (properly escapes quotes, newlines, etc.)
271
- const jsonEscapedCode = JSON.stringify(code)
272
-
273
- // Transform JSX
274
- const transformedCode = transformExpressionJSX(code)
275
-
276
- return `
277
- // Expression: ${commentCode}${code.length > 100 ? '...' : ''}
278
- // Dependencies: ${JSON.stringify({
279
- loaderData: dependencies.usesLoaderData,
280
- props: dependencies.usesProps,
281
- stores: dependencies.usesStores,
282
- state: dependencies.usesState
283
- })}
284
- const ${id} = (${paramList}) => {
285
- try {
286
- ${contextCode}
287
- return ${transformedCode};
288
- }
289
- } catch (e) {
290
- console.warn('[Zenith] Expression evaluation error:', ${jsonEscapedCode}, e);
291
- return undefined;
292
- }
293
- };`
294
- }
295
-
296
- /**
297
- * Analyze all expressions in a template
298
- */
299
- export function analyzeAllExpressions(
300
- expressions: ExpressionIR[],
301
- filePath: string,
302
- declaredLoaderProps: string[] = [],
303
- declaredProps: string[] = [],
304
- declaredStores: string[] = []
305
- ): ExpressionDataDependencies[] {
306
- const dependencies = expressions.map(expr =>
307
- analyzeExpressionDependencies(expr, declaredLoaderProps, declaredProps, declaredStores)
308
- )
309
-
310
- // Validate all dependencies
311
- for (const dep of dependencies) {
312
- validateDataDependencies(dep, filePath, declaredLoaderProps, declaredProps, declaredStores)
313
- }
314
-
315
- return dependencies
316
- }
317
-