@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,292 +0,0 @@
1
- /**
2
- * Invariant Validation
3
- *
4
- * Compile-time checks that enforce Zenith's non-negotiable invariants.
5
- * If any invariant is violated, compilation fails immediately with a clear explanation.
6
- *
7
- * INVARIANTS:
8
- * 1. Components are structural only — no reactive scopes, no state
9
- * 2. Reactivity is scope-owned — flows through components, never into them
10
- * 3. Slot projection preserves identity — loopContext is preserved or merged upward
11
- * 4. Attribute ownership belongs to usage — must be forwarded to semantic root
12
- * 5. All resolution is compile-time — no unresolved components
13
- * 6. Failure is a compiler error — no silent degradation
14
- */
15
-
16
- import type { ZenIR, TemplateNode, ElementNode, ComponentNode, LoopContext } from '../ir/types'
17
- import { InvariantError } from '../errors/compilerError'
18
-
19
- /**
20
- * Invariant Codes
21
- *
22
- * Each invariant has a unique ID for tracking and documentation.
23
- */
24
- export const INVARIANT = {
25
- LOOP_CONTEXT_LOST: 'INV001',
26
- ATTRIBUTE_NOT_FORWARDED: 'INV002',
27
- UNRESOLVED_COMPONENT: 'INV003',
28
- REACTIVE_BOUNDARY: 'INV004',
29
- TEMPLATE_TAG: 'INV005',
30
- SLOT_ATTRIBUTE: 'INV006',
31
- ORPHAN_COMPOUND: 'INV007',
32
- NON_ENUMERABLE_JSX: 'INV008',
33
- } as const
34
-
35
- /**
36
- * Guarantee Messages
37
- *
38
- * Human-readable explanations of what each invariant guarantees.
39
- */
40
- const GUARANTEES: Record<string, string> = {
41
- [INVARIANT.LOOP_CONTEXT_LOST]:
42
- 'Slot content retains its original reactive scope. Expressions and event handlers continue to work after projection.',
43
- [INVARIANT.ATTRIBUTE_NOT_FORWARDED]:
44
- 'Attributes passed to components are forwarded to the semantic root element.',
45
- [INVARIANT.UNRESOLVED_COMPONENT]:
46
- 'All components are resolved at compile time. No runtime component discovery.',
47
- [INVARIANT.REACTIVE_BOUNDARY]:
48
- 'Components are purely structural transforms. They do not create reactive scopes.',
49
- [INVARIANT.TEMPLATE_TAG]:
50
- 'Named slots use compound component pattern (Card.Header), not <template> tags.',
51
- [INVARIANT.SLOT_ATTRIBUTE]:
52
- 'Named slots use compound component pattern (Card.Header), not slot="" attributes.',
53
- [INVARIANT.ORPHAN_COMPOUND]:
54
- 'Compound slot markers (Card.Header) must be direct children of their parent component.',
55
- [INVARIANT.NON_ENUMERABLE_JSX]:
56
- 'JSX expressions must have statically enumerable output. The compiler must know all possible DOM shapes at compile time.',
57
- }
58
-
59
- /**
60
- * Validate all invariants on a compiled IR
61
- *
62
- * Called after component resolution to ensure all invariants hold.
63
- * Throws InvariantError if any invariant is violated.
64
- */
65
- export function validateInvariants(ir: ZenIR, filePath: string): void {
66
- validateNoUnresolvedComponents(ir.template.nodes, filePath)
67
- // Additional invariant checks can be added here
68
- }
69
-
70
- /**
71
- * INV003: Validate that no unresolved components remain
72
- *
73
- * After component resolution, all ComponentNode instances should be
74
- * resolved to ElementNode instances. If any remain, the compiler failed.
75
- */
76
- export function validateNoUnresolvedComponents(
77
- nodes: TemplateNode[],
78
- filePath: string
79
- ): void {
80
- for (const node of nodes) {
81
- checkNodeForUnresolvedComponent(node, filePath)
82
- }
83
- }
84
-
85
- function checkNodeForUnresolvedComponent(node: TemplateNode, filePath: string): void {
86
- if (node.type === 'component') {
87
- throw new InvariantError(
88
- INVARIANT.UNRESOLVED_COMPONENT,
89
- `Unresolved component: <${node.name}>. Component was not found or failed to resolve.`,
90
- GUARANTEES[INVARIANT.UNRESOLVED_COMPONENT]!,
91
- filePath,
92
- node.location.line,
93
- node.location.column
94
- )
95
- }
96
-
97
- if (node.type === 'element') {
98
- for (const child of node.children) {
99
- checkNodeForUnresolvedComponent(child, filePath)
100
- }
101
- }
102
- }
103
-
104
- /**
105
- * INV005: Validate no <template> tags are used
106
- *
107
- * Zenith uses compound component pattern for named slots.
108
- * <template> tags are a different mental model and are forbidden.
109
- */
110
- export function validateNoTemplateTags(
111
- nodes: TemplateNode[],
112
- filePath: string
113
- ): void {
114
- for (const node of nodes) {
115
- checkNodeForTemplateTag(node, filePath)
116
- }
117
- }
118
-
119
- function checkNodeForTemplateTag(node: TemplateNode, filePath: string): void {
120
- if (node.type === 'element' && node.tag === 'template') {
121
- throw new InvariantError(
122
- INVARIANT.TEMPLATE_TAG,
123
- `<template> tags are forbidden in Zenith. Use compound components (e.g., Card.Header) for named slots.`,
124
- GUARANTEES[INVARIANT.TEMPLATE_TAG]!,
125
- filePath,
126
- node.location.line,
127
- node.location.column
128
- )
129
- }
130
-
131
- if (node.type === 'element') {
132
- for (const child of node.children) {
133
- checkNodeForTemplateTag(child, filePath)
134
- }
135
- }
136
- }
137
-
138
- /**
139
- * INV006: Validate no slot="" attributes are used
140
- *
141
- * Zenith uses compound component pattern, not slot props.
142
- */
143
- export function validateNoSlotAttributes(
144
- nodes: TemplateNode[],
145
- filePath: string
146
- ): void {
147
- for (const node of nodes) {
148
- checkNodeForSlotAttribute(node, filePath)
149
- }
150
- }
151
-
152
- function checkNodeForSlotAttribute(node: TemplateNode, filePath: string): void {
153
- if (node.type === 'element') {
154
- const slotAttr = node.attributes.find(attr => attr.name === 'slot')
155
- if (slotAttr) {
156
- throw new InvariantError(
157
- INVARIANT.SLOT_ATTRIBUTE,
158
- `slot="${typeof slotAttr.value === 'string' ? slotAttr.value : '...'}" attribute is forbidden. Use compound components (e.g., Card.Header) for named slots.`,
159
- GUARANTEES[INVARIANT.SLOT_ATTRIBUTE]!,
160
- filePath,
161
- slotAttr.location.line,
162
- slotAttr.location.column
163
- )
164
- }
165
-
166
- for (const child of node.children) {
167
- checkNodeForSlotAttribute(child, filePath)
168
- }
169
- }
170
-
171
- if (node.type === 'component') {
172
- for (const child of node.children) {
173
- checkNodeForSlotAttribute(child, filePath)
174
- }
175
- }
176
- }
177
-
178
- /**
179
- * INV001: Validate loopContext is preserved during slot projection
180
- *
181
- * When slot content is moved from the usage site to the slot target,
182
- * the loopContext must be preserved so reactivity continues to work.
183
- *
184
- * @param originalNodes - Nodes before slot projection
185
- * @param projectedNodes - Nodes after slot projection
186
- */
187
- export function validateLoopContextPreservation(
188
- originalNodes: TemplateNode[],
189
- projectedNodes: TemplateNode[],
190
- filePath: string
191
- ): void {
192
- // Collect all loopContext from original nodes
193
- const originalContexts = collectLoopContexts(originalNodes)
194
-
195
- // Verify all contexts are still present in projected nodes
196
- const projectedContexts = collectLoopContexts(projectedNodes)
197
-
198
- for (const entry of Array.from(originalContexts.entries())) {
199
- const [nodeId, context] = entry
200
- const projected = projectedContexts.get(nodeId)
201
- if (context && !projected) {
202
- // loopContext was lost during projection
203
- // This is a compiler bug, not a user error
204
- throw new InvariantError(
205
- INVARIANT.LOOP_CONTEXT_LOST,
206
- `Reactive scope was lost during slot projection. This is a Zenith compiler bug.`,
207
- GUARANTEES[INVARIANT.LOOP_CONTEXT_LOST]!,
208
- filePath,
209
- 1, // We don't have precise location, use line 1
210
- 1
211
- )
212
- }
213
- }
214
- }
215
-
216
- function collectLoopContexts(nodes: TemplateNode[]): Map<string, LoopContext | undefined> {
217
- const contexts = new Map<string, LoopContext | undefined>()
218
- let nodeId = 0
219
-
220
- function visit(node: TemplateNode): void {
221
- const id = `node_${nodeId++}`
222
-
223
- if (node.type === 'expression') {
224
- contexts.set(id, node.loopContext)
225
- } else if (node.type === 'element') {
226
- contexts.set(id, node.loopContext)
227
- for (const attr of node.attributes) {
228
- if (attr.loopContext) {
229
- contexts.set(`${id}_attr_${attr.name}`, attr.loopContext)
230
- }
231
- }
232
- for (const child of node.children) {
233
- visit(child)
234
- }
235
- } else if (node.type === 'component') {
236
- contexts.set(id, node.loopContext)
237
- for (const child of node.children) {
238
- visit(child)
239
- }
240
- }
241
- }
242
-
243
- for (const node of nodes) {
244
- visit(node)
245
- }
246
-
247
- return contexts
248
- }
249
-
250
- /**
251
- * INV007: Throw error for orphan compound slot markers
252
- *
253
- * Called when a compound component (Card.Header) is found outside
254
- * its parent component context.
255
- */
256
- export function throwOrphanCompoundError(
257
- componentName: string,
258
- parentName: string,
259
- filePath: string,
260
- line: number,
261
- column: number
262
- ): never {
263
- throw new InvariantError(
264
- INVARIANT.ORPHAN_COMPOUND,
265
- `<${componentName}> must be a direct child of <${parentName}>. Compound slot markers cannot be used outside their parent component.`,
266
- GUARANTEES[INVARIANT.ORPHAN_COMPOUND]!,
267
- filePath,
268
- line,
269
- column
270
- )
271
- }
272
-
273
- /**
274
- * INV003: Throw error for unresolved component
275
- *
276
- * Called when a component definition cannot be found.
277
- */
278
- export function throwUnresolvedComponentError(
279
- componentName: string,
280
- filePath: string,
281
- line: number,
282
- column: number
283
- ): never {
284
- throw new InvariantError(
285
- INVARIANT.UNRESOLVED_COMPONENT,
286
- `Component <${componentName}> not found. All components must be defined in the components directory.`,
287
- GUARANTEES[INVARIANT.UNRESOLVED_COMPONENT]!,
288
- filePath,
289
- line,
290
- column
291
- )
292
- }
@@ -1,168 +0,0 @@
1
- /**
2
- * Expression Validation
3
- *
4
- * Phase 8/9/10: Compile-time validation of all expressions
5
- *
6
- * Ensures all expressions are valid JavaScript and will not cause runtime errors.
7
- * Build fails immediately if any expression is invalid.
8
- */
9
-
10
- import type { ExpressionIR } from '../ir/types'
11
- import { CompilerError } from '../errors/compilerError'
12
-
13
- /**
14
- * Validation result
15
- */
16
- export interface ValidationResult {
17
- valid: boolean
18
- errors: CompilerError[]
19
- }
20
-
21
- /**
22
- * Validate all expressions in the IR
23
- *
24
- * @param expressions - Array of expressions to validate
25
- * @param filePath - Source file path for error reporting
26
- * @returns Validation result with errors
27
- */
28
- export function validateExpressions(
29
- expressions: ExpressionIR[],
30
- filePath: string
31
- ): ValidationResult {
32
- const errors: CompilerError[] = []
33
-
34
- for (const expr of expressions) {
35
- const exprErrors = validateSingleExpression(expr, filePath)
36
- errors.push(...exprErrors)
37
- }
38
-
39
- return {
40
- valid: errors.length === 0,
41
- errors
42
- }
43
- }
44
-
45
- /**
46
- * Validate a single expression
47
- */
48
- function validateSingleExpression(
49
- expr: ExpressionIR,
50
- filePath: string
51
- ): CompilerError[] {
52
- const errors: CompilerError[] = []
53
- const { id, code, location } = expr
54
-
55
- // Basic syntax validation using a safe approach
56
- // We don't execute the code, just validate syntax
57
- // Note: Expressions may contain JSX/HTML syntax (e.g., condition && <element>)
58
- // which is not valid JavaScript but is valid in our expression language.
59
- // We skip strict JavaScript validation for expressions that contain JSX.
60
-
61
- const hasJSX = /<[a-zA-Z]/.test(code) || /\/>/.test(code)
62
-
63
- if (!hasJSX) {
64
- // Only validate JavaScript syntax if there's no JSX
65
- // Note: Using Function constructor here is for syntax validation only (compile-time)
66
- // This is safe because:
67
- // 1. It's only called at compile time, not runtime
68
- // 2. We're only checking syntax, not executing the code
69
- // 3. The actual runtime uses pre-compiled functions, not Function constructor
70
- try {
71
- // Use Function constructor to validate syntax (doesn't execute)
72
- // This is compile-time only - runtime never uses Function constructor
73
- new Function('state', 'loaderData', 'props', 'stores', `return ${code}`)
74
- } catch (error: any) {
75
- errors.push(
76
- new CompilerError(
77
- `Invalid expression syntax: ${code}\n${error.message}`,
78
- filePath,
79
- location.line,
80
- location.column
81
- )
82
- )
83
- }
84
- }
85
- // If hasJSX, we skip JavaScript validation - JSX syntax is handled by the parser/runtime
86
-
87
- // Check for dangerous patterns
88
- if (code.includes('eval(') || code.includes('Function(') || code.includes('with (')) {
89
- errors.push(
90
- new CompilerError(
91
- `Expression contains unsafe code: ${code}`,
92
- filePath,
93
- location.line,
94
- location.column
95
- )
96
- )
97
- }
98
-
99
- // Check for undefined global references (basic heuristic)
100
- // This is a simple check - can be enhanced with AST parsing
101
- const globalPattern = /\b(window|document|console|globalThis)\./g
102
- const matches = code.match(globalPattern)
103
- if (matches && matches.length > 0) {
104
- // Warn but don't fail - some global access might be intentional
105
- // In a stricter mode, we could fail here
106
- }
107
-
108
- // Check for common syntax errors
109
- const openBraces = (code.match(/\{/g) || []).length
110
- const closeBraces = (code.match(/\}/g) || []).length
111
- const openParens = (code.match(/\(/g) || []).length
112
- const closeParens = (code.match(/\)/g) || []).length
113
- const openBrackets = (code.match(/\[/g) || []).length
114
- const closeBrackets = (code.match(/\]/g) || []).length
115
-
116
- if (openBraces !== closeBraces) {
117
- errors.push(
118
- new CompilerError(
119
- `Mismatched braces in expression: ${code}`,
120
- filePath,
121
- location.line,
122
- location.column
123
- )
124
- )
125
- }
126
-
127
- if (openParens !== closeParens) {
128
- errors.push(
129
- new CompilerError(
130
- `Mismatched parentheses in expression: ${code}`,
131
- filePath,
132
- location.line,
133
- location.column
134
- )
135
- )
136
- }
137
-
138
- if (openBrackets !== closeBrackets) {
139
- errors.push(
140
- new CompilerError(
141
- `Mismatched brackets in expression: ${code}`,
142
- filePath,
143
- location.line,
144
- location.column
145
- )
146
- )
147
- }
148
-
149
- return errors
150
- }
151
-
152
- /**
153
- * Validate and throw if invalid
154
- *
155
- * @throws CompilerError if any expression is invalid
156
- */
157
- export function validateExpressionsOrThrow(
158
- expressions: ExpressionIR[],
159
- filePath: string
160
- ): void {
161
- const result = validateExpressions(expressions, filePath)
162
-
163
- if (!result.valid && result.errors.length > 0) {
164
- // Throw the first error (can be enhanced to collect all)
165
- throw result.errors[0]
166
- }
167
- }
168
-
@@ -1,16 +0,0 @@
1
- /**
2
- * Zenith Config
3
- *
4
- * Public exports for zenith/config
5
- */
6
-
7
- export { defineConfig } from './types';
8
- export type {
9
- ZenithConfig,
10
- ZenithPlugin,
11
- PluginContext,
12
- ContentSourceConfig,
13
- ContentPluginOptions,
14
- ContentItem
15
- } from './types';
16
- export { loadZenithConfig, hasZenithConfig } from './loader';
@@ -1,69 +0,0 @@
1
- /**
2
- * Zenith Config Loader
3
- *
4
- * Loads zenith.config.ts from the project root
5
- */
6
-
7
- import fs from 'node:fs';
8
- import path from 'node:path';
9
- import type { ZenithConfig } from './types';
10
-
11
- /**
12
- * Load zenith.config.ts from the project root
13
- *
14
- * @param projectRoot - Absolute path to the project root
15
- * @returns Parsed ZenithConfig or empty config if not found
16
- */
17
- export async function loadZenithConfig(projectRoot: string): Promise<ZenithConfig> {
18
- // Check for TypeScript config first, then JavaScript
19
- const configPaths = [
20
- path.join(projectRoot, 'zenith.config.ts'),
21
- path.join(projectRoot, 'zenith.config.js'),
22
- path.join(projectRoot, 'zenith.config.mjs'),
23
- ];
24
-
25
- let configPath: string | null = null;
26
- for (const p of configPaths) {
27
- if (fs.existsSync(p)) {
28
- configPath = p;
29
- break;
30
- }
31
- }
32
-
33
- if (!configPath) {
34
- // No config file found, return empty config
35
- return { plugins: [] };
36
- }
37
-
38
- try {
39
- // Use dynamic import to load the config
40
- // Bun supports importing TS files directly
41
- const configModule = await import(configPath);
42
- const config = configModule.default || configModule;
43
-
44
- // Validate basic structure
45
- if (typeof config !== 'object' || config === null) {
46
- console.warn(`[Zenith] Invalid config format in ${configPath}`);
47
- return { plugins: [] };
48
- }
49
-
50
- return config as ZenithConfig;
51
- } catch (error: unknown) {
52
- const message = error instanceof Error ? error.message : String(error);
53
- console.error(`[Zenith] Failed to load config from ${configPath}:`, message);
54
- return { plugins: [] };
55
- }
56
- }
57
-
58
- /**
59
- * Check if a zenith.config.ts exists in the project
60
- */
61
- export function hasZenithConfig(projectRoot: string): boolean {
62
- const configPaths = [
63
- path.join(projectRoot, 'zenith.config.ts'),
64
- path.join(projectRoot, 'zenith.config.js'),
65
- path.join(projectRoot, 'zenith.config.mjs'),
66
- ];
67
-
68
- return configPaths.some(p => fs.existsSync(p));
69
- }
@@ -1,89 +0,0 @@
1
- /**
2
- * Zenith Config Types
3
- *
4
- * Configuration interfaces for zenith.config.ts
5
- */
6
-
7
- // ============================================
8
- // Content Plugin Types
9
- // ============================================
10
-
11
- /**
12
- * Configuration for a content source
13
- */
14
- export interface ContentSourceConfig {
15
- /** Root directory relative to project root (e.g., "../zenith-docs" or "content") */
16
- root: string;
17
- /** Folders to include from the root (e.g., ["documentation"]). Defaults to all. */
18
- include?: string[];
19
- /** Folders to exclude from the root (e.g., ["changelog"]) */
20
- exclude?: string[];
21
- }
22
-
23
- /**
24
- * Options for the content plugin
25
- */
26
- export interface ContentPluginOptions {
27
- /** Named content sources mapped to their configuration */
28
- sources?: Record<string, ContentSourceConfig>;
29
- /** Legacy: Single content directory (deprecated, use sources instead) */
30
- contentDir?: string;
31
- }
32
-
33
- // ============================================
34
- // Core Plugin Types
35
- // ============================================
36
-
37
- /**
38
- * Context passed to plugins during setup
39
- */
40
- export interface PluginContext {
41
- /** Absolute path to project root */
42
- projectRoot: string;
43
- /** Set content data for the runtime */
44
- setContentData: (data: Record<string, ContentItem[]>) => void;
45
- /** Additional options passed from config */
46
- options?: Record<string, unknown>;
47
- }
48
-
49
- /**
50
- * A content item loaded from a source
51
- */
52
- export interface ContentItem {
53
- id?: string | number;
54
- slug?: string | null;
55
- collection?: string | null;
56
- content?: string | null;
57
- [key: string]: unknown;
58
- }
59
-
60
- /**
61
- * A Zenith plugin definition
62
- */
63
- export interface ZenithPlugin {
64
- /** Unique plugin name */
65
- name: string;
66
- /** Setup function called during initialization */
67
- setup: (ctx: PluginContext) => void | Promise<void>;
68
- /** Plugin-specific configuration (preserved for reference) */
69
- config?: unknown;
70
- }
71
-
72
- // ============================================
73
- // Main Config Types
74
- // ============================================
75
-
76
- /**
77
- * Zenith configuration object
78
- */
79
- export interface ZenithConfig {
80
- /** List of plugins to load */
81
- plugins?: ZenithPlugin[];
82
- }
83
-
84
- /**
85
- * Define a Zenith configuration with full type safety
86
- */
87
- export function defineConfig(config: ZenithConfig): ZenithConfig {
88
- return config;
89
- }