@zenithbuild/compiler 1.0.2

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 (145) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/dist/build-analyzer.d.ts +44 -0
  4. package/dist/build-analyzer.js +87 -0
  5. package/dist/bundler.d.ts +31 -0
  6. package/dist/bundler.js +86 -0
  7. package/dist/core/components/index.d.ts +9 -0
  8. package/dist/core/components/index.js +13 -0
  9. package/dist/core/config/index.d.ts +11 -0
  10. package/dist/core/config/index.js +10 -0
  11. package/dist/core/config/loader.d.ts +17 -0
  12. package/dist/core/config/loader.js +60 -0
  13. package/dist/core/config/types.d.ts +98 -0
  14. package/dist/core/config/types.js +32 -0
  15. package/dist/core/index.d.ts +7 -0
  16. package/dist/core/index.js +6 -0
  17. package/dist/core/lifecycle/index.d.ts +16 -0
  18. package/dist/core/lifecycle/index.js +19 -0
  19. package/dist/core/lifecycle/zen-mount.d.ts +66 -0
  20. package/dist/core/lifecycle/zen-mount.js +151 -0
  21. package/dist/core/lifecycle/zen-unmount.d.ts +54 -0
  22. package/dist/core/lifecycle/zen-unmount.js +76 -0
  23. package/dist/core/plugins/bridge.d.ts +116 -0
  24. package/dist/core/plugins/bridge.js +121 -0
  25. package/dist/core/plugins/index.d.ts +6 -0
  26. package/dist/core/plugins/index.js +6 -0
  27. package/dist/core/plugins/registry.d.ts +67 -0
  28. package/dist/core/plugins/registry.js +113 -0
  29. package/dist/core/reactivity/index.d.ts +30 -0
  30. package/dist/core/reactivity/index.js +33 -0
  31. package/dist/core/reactivity/tracking.d.ts +74 -0
  32. package/dist/core/reactivity/tracking.js +136 -0
  33. package/dist/core/reactivity/zen-batch.d.ts +45 -0
  34. package/dist/core/reactivity/zen-batch.js +54 -0
  35. package/dist/core/reactivity/zen-effect.d.ts +48 -0
  36. package/dist/core/reactivity/zen-effect.js +98 -0
  37. package/dist/core/reactivity/zen-memo.d.ts +43 -0
  38. package/dist/core/reactivity/zen-memo.js +100 -0
  39. package/dist/core/reactivity/zen-ref.d.ts +44 -0
  40. package/dist/core/reactivity/zen-ref.js +34 -0
  41. package/dist/core/reactivity/zen-signal.d.ts +48 -0
  42. package/dist/core/reactivity/zen-signal.js +84 -0
  43. package/dist/core/reactivity/zen-state.d.ts +35 -0
  44. package/dist/core/reactivity/zen-state.js +147 -0
  45. package/dist/core/reactivity/zen-untrack.d.ts +38 -0
  46. package/dist/core/reactivity/zen-untrack.js +41 -0
  47. package/dist/css/index.d.ts +73 -0
  48. package/dist/css/index.js +246 -0
  49. package/dist/discovery/componentDiscovery.d.ts +42 -0
  50. package/dist/discovery/componentDiscovery.js +56 -0
  51. package/dist/discovery/layouts.d.ts +13 -0
  52. package/dist/discovery/layouts.js +41 -0
  53. package/dist/errors/compilerError.d.ts +31 -0
  54. package/dist/errors/compilerError.js +51 -0
  55. package/dist/finalize/finalizeOutput.d.ts +32 -0
  56. package/dist/finalize/finalizeOutput.js +62 -0
  57. package/dist/finalize/generateFinalBundle.d.ts +24 -0
  58. package/dist/finalize/generateFinalBundle.js +68 -0
  59. package/dist/index.d.ts +36 -0
  60. package/dist/index.js +51 -0
  61. package/dist/ir/types.d.ts +181 -0
  62. package/dist/ir/types.js +8 -0
  63. package/dist/output/types.d.ts +30 -0
  64. package/dist/output/types.js +6 -0
  65. package/dist/parse/detectMapExpressions.d.ts +45 -0
  66. package/dist/parse/detectMapExpressions.js +77 -0
  67. package/dist/parse/parseScript.d.ts +8 -0
  68. package/dist/parse/parseScript.js +36 -0
  69. package/dist/parse/parseTemplate.d.ts +11 -0
  70. package/dist/parse/parseTemplate.js +487 -0
  71. package/dist/parse/parseZenFile.d.ts +11 -0
  72. package/dist/parse/parseZenFile.js +50 -0
  73. package/dist/parse/scriptAnalysis.d.ts +25 -0
  74. package/dist/parse/scriptAnalysis.js +60 -0
  75. package/dist/parse/trackLoopContext.d.ts +20 -0
  76. package/dist/parse/trackLoopContext.js +62 -0
  77. package/dist/parseZenFile.d.ts +10 -0
  78. package/dist/parseZenFile.js +55 -0
  79. package/dist/runtime/analyzeAndEmit.d.ts +20 -0
  80. package/dist/runtime/analyzeAndEmit.js +70 -0
  81. package/dist/runtime/build.d.ts +6 -0
  82. package/dist/runtime/build.js +13 -0
  83. package/dist/runtime/bundle-generator.d.ts +27 -0
  84. package/dist/runtime/bundle-generator.js +1263 -0
  85. package/dist/runtime/client-runtime.d.ts +41 -0
  86. package/dist/runtime/client-runtime.js +397 -0
  87. package/dist/runtime/dataExposure.d.ts +52 -0
  88. package/dist/runtime/dataExposure.js +227 -0
  89. package/dist/runtime/generateDOM.d.ts +21 -0
  90. package/dist/runtime/generateDOM.js +194 -0
  91. package/dist/runtime/generateHydrationBundle.d.ts +15 -0
  92. package/dist/runtime/generateHydrationBundle.js +399 -0
  93. package/dist/runtime/hydration.d.ts +53 -0
  94. package/dist/runtime/hydration.js +271 -0
  95. package/dist/runtime/navigation.d.ts +58 -0
  96. package/dist/runtime/navigation.js +372 -0
  97. package/dist/runtime/serve.d.ts +13 -0
  98. package/dist/runtime/serve.js +76 -0
  99. package/dist/runtime/thinRuntime.d.ts +23 -0
  100. package/dist/runtime/thinRuntime.js +158 -0
  101. package/dist/runtime/transformIR.d.ts +19 -0
  102. package/dist/runtime/transformIR.js +285 -0
  103. package/dist/runtime/wrapExpression.d.ts +24 -0
  104. package/dist/runtime/wrapExpression.js +76 -0
  105. package/dist/runtime/wrapExpressionWithLoop.d.ts +17 -0
  106. package/dist/runtime/wrapExpressionWithLoop.js +75 -0
  107. package/dist/spa-build.d.ts +26 -0
  108. package/dist/spa-build.js +866 -0
  109. package/dist/ssg-build.d.ts +32 -0
  110. package/dist/ssg-build.js +408 -0
  111. package/dist/test/analyze-emit.test.d.ts +1 -0
  112. package/dist/test/analyze-emit.test.js +88 -0
  113. package/dist/test/bundler-contract.test.d.ts +1 -0
  114. package/dist/test/bundler-contract.test.js +137 -0
  115. package/dist/test/compiler-authority.test.d.ts +1 -0
  116. package/dist/test/compiler-authority.test.js +90 -0
  117. package/dist/test/component-instance-test.d.ts +1 -0
  118. package/dist/test/component-instance-test.js +115 -0
  119. package/dist/test/error-native-bridge.test.d.ts +1 -0
  120. package/dist/test/error-native-bridge.test.js +51 -0
  121. package/dist/test/error-serialization.test.d.ts +1 -0
  122. package/dist/test/error-serialization.test.js +38 -0
  123. package/dist/test/macro-inlining.test.d.ts +1 -0
  124. package/dist/test/macro-inlining.test.js +178 -0
  125. package/dist/test/validate-test.d.ts +6 -0
  126. package/dist/test/validate-test.js +95 -0
  127. package/dist/transform/classifyExpression.d.ts +46 -0
  128. package/dist/transform/classifyExpression.js +354 -0
  129. package/dist/transform/componentResolver.d.ts +15 -0
  130. package/dist/transform/componentResolver.js +30 -0
  131. package/dist/transform/expressionTransformer.d.ts +19 -0
  132. package/dist/transform/expressionTransformer.js +333 -0
  133. package/dist/transform/fragmentLowering.d.ts +25 -0
  134. package/dist/transform/fragmentLowering.js +468 -0
  135. package/dist/transform/layoutProcessor.d.ts +5 -0
  136. package/dist/transform/layoutProcessor.js +34 -0
  137. package/dist/transform/transformTemplate.d.ts +11 -0
  138. package/dist/transform/transformTemplate.js +33 -0
  139. package/dist/validate/invariants.d.ts +23 -0
  140. package/dist/validate/invariants.js +55 -0
  141. package/native/compiler-native/compiler-native.node +0 -0
  142. package/native/compiler-native/index.d.ts +113 -0
  143. package/native/compiler-native/index.js +19 -0
  144. package/native/compiler-native/package.json +19 -0
  145. package/package.json +49 -0
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Zenith Plugin Registry
3
+ *
4
+ * Manages plugin registration and initialization
5
+ *
6
+ * ═══════════════════════════════════════════════════════════════════════════════
7
+ * HOOK OWNERSHIP RULE (CANONICAL)
8
+ * ═══════════════════════════════════════════════════════════════════════════════
9
+ *
10
+ * The plugin registry is part of core infrastructure.
11
+ * It MUST remain plugin-agnostic:
12
+ * - No plugin-specific types
13
+ * - No plugin-specific logic
14
+ * - Generic data handling only
15
+ *
16
+ * Plugins own their data structures; core provides the storage mechanism.
17
+ * ═══════════════════════════════════════════════════════════════════════════════
18
+ */
19
+ /**
20
+ * Global plugin data store
21
+ *
22
+ * Plugins store their data here using namespaced keys.
23
+ * Core does not interpret this data - it just stores and serves it.
24
+ */
25
+ const pluginDataStore = {};
26
+ /**
27
+ * Get all plugin data (for runtime access)
28
+ */
29
+ export function getPluginData() {
30
+ return { ...pluginDataStore };
31
+ }
32
+ /**
33
+ * Get plugin data by namespace
34
+ */
35
+ export function getPluginDataByNamespace(namespace) {
36
+ return pluginDataStore[namespace] || [];
37
+ }
38
+ /**
39
+ * Plugin registry for managing Zenith plugins
40
+ */
41
+ export class PluginRegistry {
42
+ plugins = new Map();
43
+ /**
44
+ * Register a plugin
45
+ */
46
+ register(plugin) {
47
+ if (this.plugins.has(plugin.name)) {
48
+ console.warn(`[Zenith] Plugin "${plugin.name}" is already registered. Overwriting.`);
49
+ }
50
+ this.plugins.set(plugin.name, plugin);
51
+ }
52
+ /**
53
+ * Get a plugin by name
54
+ */
55
+ get(name) {
56
+ return this.plugins.get(name);
57
+ }
58
+ /**
59
+ * Check if a plugin is registered
60
+ */
61
+ has(name) {
62
+ return this.plugins.has(name);
63
+ }
64
+ /**
65
+ * Get all registered plugins
66
+ */
67
+ all() {
68
+ return Array.from(this.plugins.values());
69
+ }
70
+ /**
71
+ * Initialize all plugins with the provided context
72
+ */
73
+ async initAll(ctx) {
74
+ for (const plugin of this.plugins.values()) {
75
+ try {
76
+ await plugin.setup(ctx);
77
+ console.log(`[Zenith] Plugin "${plugin.name}" initialized`);
78
+ }
79
+ catch (error) {
80
+ const message = error instanceof Error ? error.message : String(error);
81
+ console.error(`[Zenith] Failed to initialize plugin "${plugin.name}":`, message);
82
+ }
83
+ }
84
+ }
85
+ /**
86
+ * Clear all registered plugins
87
+ */
88
+ clear() {
89
+ this.plugins.clear();
90
+ // Also clear plugin data
91
+ for (const key of Object.keys(pluginDataStore)) {
92
+ delete pluginDataStore[key];
93
+ }
94
+ }
95
+ }
96
+ /**
97
+ * Create a plugin context for initialization
98
+ *
99
+ * Uses a generic data setter that stores data by namespace.
100
+ * Plugins define their own data structures internally.
101
+ *
102
+ * @param projectRoot - Absolute path to the project root
103
+ * @returns A PluginContext for plugin initialization
104
+ */
105
+ export function createPluginContext(projectRoot) {
106
+ return {
107
+ projectRoot,
108
+ setPluginData: (namespace, data) => {
109
+ pluginDataStore[namespace] = data;
110
+ },
111
+ options: {}
112
+ };
113
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Zenith Reactivity System
3
+ *
4
+ * This module exports all reactive primitives for the Zenith framework.
5
+ *
6
+ * Exports both explicit `zen*` names (internal) and clean aliases (public DX).
7
+ */
8
+ import { zenSignal as _zenSignal, type Signal } from './zen-signal';
9
+ import { zenState as _zenState } from './zen-state';
10
+ import { zenEffect as _zenEffect, type EffectFn, type DisposeFn } from './zen-effect';
11
+ import { zenMemo as _zenMemo, type Memo } from './zen-memo';
12
+ import { zenRef as _zenRef, type Ref } from './zen-ref';
13
+ import { zenBatch as _zenBatch } from './zen-batch';
14
+ import { zenUntrack as _zenUntrack } from './zen-untrack';
15
+ export declare const zenSignal: typeof _zenSignal;
16
+ export declare const zenState: typeof _zenState;
17
+ export declare const zenEffect: typeof _zenEffect;
18
+ export declare const zenMemo: typeof _zenMemo;
19
+ export declare const zenRef: typeof _zenRef;
20
+ export declare const zenBatch: typeof _zenBatch;
21
+ export declare const zenUntrack: typeof _zenUntrack;
22
+ export type { Signal, Memo, Ref, EffectFn, DisposeFn };
23
+ export { type Subscriber, type TrackingContext, trackDependency, notifySubscribers, getCurrentContext, pushContext, popContext, cleanupContext, runUntracked, startBatch, endBatch, isBatching } from './tracking';
24
+ export declare const signal: typeof _zenSignal;
25
+ export declare const state: typeof _zenState;
26
+ export declare const effect: typeof _zenEffect;
27
+ export declare const memo: typeof _zenMemo;
28
+ export declare const ref: typeof _zenRef;
29
+ export declare const batch: typeof _zenBatch;
30
+ export declare const untrack: typeof _zenUntrack;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Zenith Reactivity System
3
+ *
4
+ * This module exports all reactive primitives for the Zenith framework.
5
+ *
6
+ * Exports both explicit `zen*` names (internal) and clean aliases (public DX).
7
+ */
8
+ // Core primitives - explicit names
9
+ import { zenSignal as _zenSignal } from './zen-signal';
10
+ import { zenState as _zenState } from './zen-state';
11
+ import { zenEffect as _zenEffect } from './zen-effect';
12
+ import { zenMemo as _zenMemo } from './zen-memo';
13
+ import { zenRef as _zenRef } from './zen-ref';
14
+ import { zenBatch as _zenBatch } from './zen-batch';
15
+ import { zenUntrack as _zenUntrack } from './zen-untrack';
16
+ // Re-export with explicit names
17
+ export const zenSignal = _zenSignal;
18
+ export const zenState = _zenState;
19
+ export const zenEffect = _zenEffect;
20
+ export const zenMemo = _zenMemo;
21
+ export const zenRef = _zenRef;
22
+ export const zenBatch = _zenBatch;
23
+ export const zenUntrack = _zenUntrack;
24
+ // Internal tracking utilities (for advanced use)
25
+ export { trackDependency, notifySubscribers, getCurrentContext, pushContext, popContext, cleanupContext, runUntracked, startBatch, endBatch, isBatching } from './tracking';
26
+ // Public DX aliases - clean names
27
+ export const signal = _zenSignal;
28
+ export const state = _zenState;
29
+ export const effect = _zenEffect;
30
+ export const memo = _zenMemo;
31
+ export const ref = _zenRef;
32
+ export const batch = _zenBatch;
33
+ export const untrack = _zenUntrack;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Zenith Reactivity Tracking System
3
+ *
4
+ * This module provides the core dependency tracking mechanism used by
5
+ * signals, effects, and memos. It uses a stack-based approach to track
6
+ * which reactive values are accessed during effect/memo execution.
7
+ *
8
+ * Key concepts:
9
+ * - Subscriber: A function that should be called when a dependency changes
10
+ * - Tracking context: The currently executing effect/memo that should collect dependencies
11
+ * - Dependency: A reactive value that an effect/memo depends on
12
+ */
13
+ /**
14
+ * A subscriber is a function that gets called when a reactive value changes
15
+ */
16
+ export type Subscriber = () => void;
17
+ /**
18
+ * Tracking context - represents an effect or memo that is collecting dependencies
19
+ */
20
+ export interface TrackingContext {
21
+ /** The function to call when dependencies change */
22
+ execute: Subscriber;
23
+ /** Set of dependency subscriber sets this context is registered with */
24
+ dependencies: Set<Set<Subscriber>>;
25
+ }
26
+ /**
27
+ * Get the current tracking context (if any)
28
+ */
29
+ export declare function getCurrentContext(): TrackingContext | undefined;
30
+ /**
31
+ * Push a new tracking context onto the stack
32
+ */
33
+ export declare function pushContext(context: TrackingContext): void;
34
+ /**
35
+ * Pop the current tracking context from the stack
36
+ */
37
+ export declare function popContext(): TrackingContext | undefined;
38
+ /**
39
+ * Track a dependency - called when a reactive value is read
40
+ *
41
+ * @param subscribers - The subscriber set of the reactive value being read
42
+ */
43
+ export declare function trackDependency(subscribers: Set<Subscriber>): void;
44
+ /**
45
+ * Notify subscribers that a reactive value has changed
46
+ *
47
+ * @param subscribers - The subscriber set to notify
48
+ */
49
+ export declare function notifySubscribers(subscribers: Set<Subscriber>): void;
50
+ /**
51
+ * Clean up a tracking context - remove it from all dependency sets
52
+ *
53
+ * @param context - The context to clean up
54
+ */
55
+ export declare function cleanupContext(context: TrackingContext): void;
56
+ /**
57
+ * Run a function without tracking dependencies
58
+ *
59
+ * @param fn - The function to run
60
+ * @returns The return value of the function
61
+ */
62
+ export declare function runUntracked<T>(fn: () => T): T;
63
+ /**
64
+ * Start a batch - defer effect execution until batch ends
65
+ */
66
+ export declare function startBatch(): void;
67
+ /**
68
+ * End a batch - run all pending effects
69
+ */
70
+ export declare function endBatch(): void;
71
+ /**
72
+ * Check if currently inside a batch
73
+ */
74
+ export declare function isBatching(): boolean;
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Zenith Reactivity Tracking System
3
+ *
4
+ * This module provides the core dependency tracking mechanism used by
5
+ * signals, effects, and memos. It uses a stack-based approach to track
6
+ * which reactive values are accessed during effect/memo execution.
7
+ *
8
+ * Key concepts:
9
+ * - Subscriber: A function that should be called when a dependency changes
10
+ * - Tracking context: The currently executing effect/memo that should collect dependencies
11
+ * - Dependency: A reactive value that an effect/memo depends on
12
+ */
13
+ /**
14
+ * Stack of currently executing tracking contexts
15
+ * When an effect runs, it pushes itself onto this stack.
16
+ * When a signal is read, it registers the top of the stack as a subscriber.
17
+ */
18
+ const trackingStack = [];
19
+ /**
20
+ * Flag to disable tracking (used by zenUntrack)
21
+ */
22
+ let trackingDisabled = false;
23
+ /**
24
+ * Batch depth counter - when > 0, effect execution is deferred
25
+ */
26
+ let batchDepth = 0;
27
+ /**
28
+ * Queue of effects to run after batch completes
29
+ */
30
+ const pendingEffects = new Set();
31
+ /**
32
+ * Get the current tracking context (if any)
33
+ */
34
+ export function getCurrentContext() {
35
+ if (trackingDisabled)
36
+ return undefined;
37
+ return trackingStack[trackingStack.length - 1];
38
+ }
39
+ /**
40
+ * Push a new tracking context onto the stack
41
+ */
42
+ export function pushContext(context) {
43
+ trackingStack.push(context);
44
+ }
45
+ /**
46
+ * Pop the current tracking context from the stack
47
+ */
48
+ export function popContext() {
49
+ return trackingStack.pop();
50
+ }
51
+ /**
52
+ * Track a dependency - called when a reactive value is read
53
+ *
54
+ * @param subscribers - The subscriber set of the reactive value being read
55
+ */
56
+ export function trackDependency(subscribers) {
57
+ const context = getCurrentContext();
58
+ if (context) {
59
+ // Register this effect as a subscriber to the signal
60
+ subscribers.add(context.execute);
61
+ // Track that this effect depends on this signal
62
+ context.dependencies.add(subscribers);
63
+ }
64
+ }
65
+ /**
66
+ * Notify subscribers that a reactive value has changed
67
+ *
68
+ * @param subscribers - The subscriber set to notify
69
+ */
70
+ export function notifySubscribers(subscribers) {
71
+ // Copy subscribers to avoid issues if the set is modified during iteration
72
+ const toNotify = [...subscribers];
73
+ for (const subscriber of toNotify) {
74
+ if (batchDepth > 0) {
75
+ // Batching - defer effect execution
76
+ pendingEffects.add(subscriber);
77
+ }
78
+ else {
79
+ // Execute immediately
80
+ subscriber();
81
+ }
82
+ }
83
+ }
84
+ /**
85
+ * Clean up a tracking context - remove it from all dependency sets
86
+ *
87
+ * @param context - The context to clean up
88
+ */
89
+ export function cleanupContext(context) {
90
+ for (const deps of context.dependencies) {
91
+ deps.delete(context.execute);
92
+ }
93
+ context.dependencies.clear();
94
+ }
95
+ /**
96
+ * Run a function without tracking dependencies
97
+ *
98
+ * @param fn - The function to run
99
+ * @returns The return value of the function
100
+ */
101
+ export function runUntracked(fn) {
102
+ const wasDisabled = trackingDisabled;
103
+ trackingDisabled = true;
104
+ try {
105
+ return fn();
106
+ }
107
+ finally {
108
+ trackingDisabled = wasDisabled;
109
+ }
110
+ }
111
+ /**
112
+ * Start a batch - defer effect execution until batch ends
113
+ */
114
+ export function startBatch() {
115
+ batchDepth++;
116
+ }
117
+ /**
118
+ * End a batch - run all pending effects
119
+ */
120
+ export function endBatch() {
121
+ batchDepth--;
122
+ if (batchDepth === 0 && pendingEffects.size > 0) {
123
+ // Run all pending effects
124
+ const effects = [...pendingEffects];
125
+ pendingEffects.clear();
126
+ for (const effect of effects) {
127
+ effect();
128
+ }
129
+ }
130
+ }
131
+ /**
132
+ * Check if currently inside a batch
133
+ */
134
+ export function isBatching() {
135
+ return batchDepth > 0;
136
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Zenith Batch - Deferred Effect Execution
3
+ *
4
+ * Batching allows you to make multiple reactive updates without
5
+ * triggering effects until all updates are complete. This improves
6
+ * performance by preventing redundant effect executions.
7
+ *
8
+ * Features:
9
+ * - Groups multiple mutations
10
+ * - Defers effect execution until batch completes
11
+ * - Supports nested batches
12
+ * - Automatically flushes on completion
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * const firstName = zenSignal('John')
17
+ * const lastName = zenSignal('Doe')
18
+ *
19
+ * zenEffect(() => {
20
+ * console.log(`${firstName()} ${lastName()}`)
21
+ * })
22
+ * // Logs: "John Doe"
23
+ *
24
+ * // Without batch - effect runs twice
25
+ * firstName('Jane') // Logs: "Jane Doe"
26
+ * lastName('Smith') // Logs: "Jane Smith"
27
+ *
28
+ * // With batch - effect runs once
29
+ * zenBatch(() => {
30
+ * firstName('Bob')
31
+ * lastName('Brown')
32
+ * })
33
+ * // Logs: "Bob Brown" (only once)
34
+ * ```
35
+ */
36
+ /**
37
+ * Execute a function with batched updates
38
+ *
39
+ * All reactive updates inside the batch will be collected,
40
+ * and effects will only run once after the batch completes.
41
+ *
42
+ * @param fn - The function to execute
43
+ * @returns The return value of the function
44
+ */
45
+ export declare function zenBatch<T>(fn: () => T): T;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Zenith Batch - Deferred Effect Execution
3
+ *
4
+ * Batching allows you to make multiple reactive updates without
5
+ * triggering effects until all updates are complete. This improves
6
+ * performance by preventing redundant effect executions.
7
+ *
8
+ * Features:
9
+ * - Groups multiple mutations
10
+ * - Defers effect execution until batch completes
11
+ * - Supports nested batches
12
+ * - Automatically flushes on completion
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * const firstName = zenSignal('John')
17
+ * const lastName = zenSignal('Doe')
18
+ *
19
+ * zenEffect(() => {
20
+ * console.log(`${firstName()} ${lastName()}`)
21
+ * })
22
+ * // Logs: "John Doe"
23
+ *
24
+ * // Without batch - effect runs twice
25
+ * firstName('Jane') // Logs: "Jane Doe"
26
+ * lastName('Smith') // Logs: "Jane Smith"
27
+ *
28
+ * // With batch - effect runs once
29
+ * zenBatch(() => {
30
+ * firstName('Bob')
31
+ * lastName('Brown')
32
+ * })
33
+ * // Logs: "Bob Brown" (only once)
34
+ * ```
35
+ */
36
+ import { startBatch, endBatch } from './tracking';
37
+ /**
38
+ * Execute a function with batched updates
39
+ *
40
+ * All reactive updates inside the batch will be collected,
41
+ * and effects will only run once after the batch completes.
42
+ *
43
+ * @param fn - The function to execute
44
+ * @returns The return value of the function
45
+ */
46
+ export function zenBatch(fn) {
47
+ startBatch();
48
+ try {
49
+ return fn();
50
+ }
51
+ finally {
52
+ endBatch();
53
+ }
54
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Zenith Effect - Auto-Tracked Side Effect
3
+ *
4
+ * Effects are functions that automatically track their reactive dependencies
5
+ * and re-run when those dependencies change. They are the bridge between
6
+ * reactive state and side effects (DOM updates, logging, API calls, etc.)
7
+ *
8
+ * Features:
9
+ * - Automatic dependency tracking (no dependency arrays)
10
+ * - Runs immediately on creation
11
+ * - Re-runs when dependencies change
12
+ * - Supports cleanup functions
13
+ * - Can be manually disposed
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const count = zenSignal(0)
18
+ *
19
+ * // Effect runs immediately, then re-runs when count changes
20
+ * const dispose = zenEffect(() => {
21
+ * console.log('Count:', count())
22
+ *
23
+ * // Optional cleanup - runs before next execution or on dispose
24
+ * return () => {
25
+ * console.log('Cleanup')
26
+ * }
27
+ * })
28
+ *
29
+ * count(1) // Logs: "Cleanup", then "Count: 1"
30
+ *
31
+ * dispose() // Cleanup and stop watching
32
+ * ```
33
+ */
34
+ /**
35
+ * Effect function type - can optionally return a cleanup function
36
+ */
37
+ export type EffectFn = () => void | (() => void);
38
+ /**
39
+ * Dispose function - call to stop the effect
40
+ */
41
+ export type DisposeFn = () => void;
42
+ /**
43
+ * Create an auto-tracked side effect
44
+ *
45
+ * @param fn - The effect function to run
46
+ * @returns A dispose function to stop the effect
47
+ */
48
+ export declare function zenEffect(fn: EffectFn): DisposeFn;
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Zenith Effect - Auto-Tracked Side Effect
3
+ *
4
+ * Effects are functions that automatically track their reactive dependencies
5
+ * and re-run when those dependencies change. They are the bridge between
6
+ * reactive state and side effects (DOM updates, logging, API calls, etc.)
7
+ *
8
+ * Features:
9
+ * - Automatic dependency tracking (no dependency arrays)
10
+ * - Runs immediately on creation
11
+ * - Re-runs when dependencies change
12
+ * - Supports cleanup functions
13
+ * - Can be manually disposed
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const count = zenSignal(0)
18
+ *
19
+ * // Effect runs immediately, then re-runs when count changes
20
+ * const dispose = zenEffect(() => {
21
+ * console.log('Count:', count())
22
+ *
23
+ * // Optional cleanup - runs before next execution or on dispose
24
+ * return () => {
25
+ * console.log('Cleanup')
26
+ * }
27
+ * })
28
+ *
29
+ * count(1) // Logs: "Cleanup", then "Count: 1"
30
+ *
31
+ * dispose() // Cleanup and stop watching
32
+ * ```
33
+ */
34
+ import { pushContext, popContext, cleanupContext } from './tracking';
35
+ /**
36
+ * Create an auto-tracked side effect
37
+ *
38
+ * @param fn - The effect function to run
39
+ * @returns A dispose function to stop the effect
40
+ */
41
+ export function zenEffect(fn) {
42
+ const state = {
43
+ fn,
44
+ cleanup: null,
45
+ context: {
46
+ execute: () => runEffect(state),
47
+ dependencies: new Set()
48
+ },
49
+ disposed: false
50
+ };
51
+ // Run the effect immediately
52
+ runEffect(state);
53
+ // Return dispose function
54
+ return () => disposeEffect(state);
55
+ }
56
+ /**
57
+ * Run an effect, tracking dependencies
58
+ */
59
+ function runEffect(state) {
60
+ if (state.disposed)
61
+ return;
62
+ // Run cleanup from previous execution
63
+ if (state.cleanup) {
64
+ state.cleanup();
65
+ state.cleanup = null;
66
+ }
67
+ // Clean up old dependencies
68
+ cleanupContext(state.context);
69
+ // Push this effect onto the tracking stack
70
+ pushContext(state.context);
71
+ try {
72
+ // Run the effect function
73
+ const result = state.fn();
74
+ // Store cleanup if returned
75
+ if (typeof result === 'function') {
76
+ state.cleanup = result;
77
+ }
78
+ }
79
+ finally {
80
+ // Pop from tracking stack
81
+ popContext();
82
+ }
83
+ }
84
+ /**
85
+ * Dispose an effect - run cleanup and stop watching
86
+ */
87
+ function disposeEffect(state) {
88
+ if (state.disposed)
89
+ return;
90
+ state.disposed = true;
91
+ // Run cleanup
92
+ if (state.cleanup) {
93
+ state.cleanup();
94
+ state.cleanup = null;
95
+ }
96
+ // Remove from all dependency sets
97
+ cleanupContext(state.context);
98
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Zenith Memo - Computed/Derived Value
3
+ *
4
+ * A memo is a lazily-evaluated, cached computation that automatically
5
+ * tracks its dependencies and only recomputes when those dependencies change.
6
+ *
7
+ * Features:
8
+ * - Lazy evaluation (only computes when read)
9
+ * - Automatic dependency tracking
10
+ * - Cached value until dependencies change
11
+ * - Read-only (no setter)
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const firstName = zenSignal('John')
16
+ * const lastName = zenSignal('Doe')
17
+ *
18
+ * // Memo computes full name, tracks firstName and lastName
19
+ * const fullName = zenMemo(() => `${firstName()} ${lastName()}`)
20
+ *
21
+ * console.log(fullName()) // "John Doe"
22
+ *
23
+ * firstName('Jane')
24
+ * console.log(fullName()) // "Jane Doe" (recomputed)
25
+ * console.log(fullName()) // "Jane Doe" (cached, no recomputation)
26
+ * ```
27
+ */
28
+ /**
29
+ * Memo interface - callable getter
30
+ */
31
+ export interface Memo<T> {
32
+ /** Get the current computed value */
33
+ (): T;
34
+ /** Peek at cached value without tracking (may be stale) */
35
+ peek(): T;
36
+ }
37
+ /**
38
+ * Create a memoized computed value
39
+ *
40
+ * @param fn - The computation function
41
+ * @returns A memo that can be read to get the computed value
42
+ */
43
+ export declare function zenMemo<T>(fn: () => T): Memo<T>;