@hypen-space/core 0.4.46 → 0.4.81

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.
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Abstract base class for Hypen WASM engine wrappers.
3
+ *
4
+ * The Hypen engine is distributed as a wasm-bindgen module — two builds:
5
+ *
6
+ * - `wasm-node` (bundler target) — used by `@hypen-space/server` on Node/Bun
7
+ * - `wasm-browser` (web target) — used by `@hypen-space/web-engine` in browsers
8
+ *
9
+ * Both builds expose an identical `WasmEngine` class; the only genuine
10
+ * platform differences are:
11
+ *
12
+ * 1. How the WASM module is *instantiated*. Node can synchronously `new
13
+ * WasmEngine()` (the bundler target auto-initializes); the browser
14
+ * target needs an async dynamic import of the JS glue code and an
15
+ * explicit `wasm_init(url)` call before any `new WasmEngine()`.
16
+ *
17
+ * 2. How host state is *unwrapped* before it crosses the WASM boundary.
18
+ * Node can use `structuredClone` (with a `__getSnapshot` fast path for
19
+ * Hypen's proxy-backed state); the browser path does a
20
+ * `JSON.parse(JSON.stringify())` round-trip plus a Map-to-Object
21
+ * conversion for the native Map values that the wasm-bindgen browser
22
+ * target returns in action payloads.
23
+ *
24
+ * Everything else — method wrappers, error classification, callback wiring,
25
+ * revision plumbing — is identical between the two. That shared surface
26
+ * lives here.
27
+ *
28
+ * Subclasses implement two abstract hooks:
29
+ *
30
+ * - `init(options?): Promise<void>` — platform-specific WASM setup. Must
31
+ * assign `this.wasmEngine` and set `this.initialized = true` on success.
32
+ *
33
+ * - `unwrapForWasm<T>(value: T): T` — platform-specific proxy-to-plain
34
+ * conversion. Called before any value crosses into WASM.
35
+ */
36
+ import type { Action, RenderCallback, ActionHandler, ComponentResolver } from "./types.js";
37
+ /**
38
+ * Shared base wrapping a wasm-bindgen `WasmEngine`. `any` here is load-
39
+ * bearing: the concrete type is `WasmEngine` from either the `wasm-node`
40
+ * or `wasm-browser` build, and those are separate generated `.d.ts`
41
+ * files that core cannot (and should not) depend on. Subclasses keep
42
+ * their own typed reference if they want stricter checking locally.
43
+ */
44
+ export declare abstract class BaseEngine {
45
+ protected wasmEngine: any;
46
+ protected initialized: boolean;
47
+ /**
48
+ * Initialize the WASM module. Platform-specific.
49
+ *
50
+ * Must assign `this.wasmEngine` and set `this.initialized = true`.
51
+ * Idempotent: must early-return if already initialized.
52
+ */
53
+ abstract init(options?: unknown): Promise<void>;
54
+ /**
55
+ * Convert a host value (possibly a Proxy, possibly containing Maps,
56
+ * possibly wrapped in Hypen's observable state) into a plain-object
57
+ * form safe to pass across the WASM boundary.
58
+ *
59
+ * Called on every `updateState` / `updateStateSparse` / `renderInto`
60
+ * / `setContext` / `registerModule` entry point.
61
+ */
62
+ protected abstract unwrapForWasm<T>(value: T): T;
63
+ /**
64
+ * Guard that throws if the engine hasn't been initialized.
65
+ * Returns the underlying WASM engine for chained access.
66
+ */
67
+ protected ensureInitialized(): any;
68
+ /**
69
+ * Set the render callback that receives patches.
70
+ */
71
+ setRenderCallback(callback: RenderCallback): void;
72
+ /**
73
+ * Set the component resolver for dynamic component composition.
74
+ */
75
+ setComponentResolver(resolver: ComponentResolver): void;
76
+ /**
77
+ * Parse and render Hypen DSL source code.
78
+ * @throws {ParseError} if the source fails to parse
79
+ * @throws {RenderError} if rendering fails
80
+ */
81
+ renderSource(source: string): void;
82
+ /**
83
+ * Render a lazy component (for lazy route loading).
84
+ */
85
+ renderLazyComponent(source: string): void;
86
+ /**
87
+ * Render a component into a specific parent node (subtree rendering).
88
+ * @throws {ParseError} if the source fails to parse
89
+ * @throws {RenderError} if the parent node is not found or rendering fails
90
+ */
91
+ renderInto(source: string, parentNodeId: string, state: Record<string, any>): void;
92
+ /**
93
+ * Apply a sparse state update.
94
+ *
95
+ * @param scope Lowercase module name to target a named module registered
96
+ * via `registerModule`. Pass `null` (or empty string) to
97
+ * target the primary module set via `setModule`.
98
+ * @param paths Changed state paths (relative to the targeted module).
99
+ * @param values Map of `path -> new value`.
100
+ * @throws {StateError} if the state patch is invalid
101
+ */
102
+ updateStateSparse(scope: string | null, paths: string[], values: Record<string, any>): void;
103
+ /**
104
+ * Apply a full-state patch. See [updateStateSparse] for `scope` semantics.
105
+ * Prefer the sparse form when only a few paths changed.
106
+ */
107
+ updateState(scope: string | null, statePatch: Record<string, any>): void;
108
+ /**
109
+ * Dispatch an action.
110
+ * @throws {HypenError} if the action dispatch fails
111
+ */
112
+ dispatchAction(name: string, payload?: any): void;
113
+ /**
114
+ * Register an action handler. Errors thrown synchronously or via rejected
115
+ * promises are caught and logged at the framework level; caller-side error
116
+ * recovery should happen inside `handler`.
117
+ *
118
+ * Action payloads may contain platform-specific native values (e.g. Maps
119
+ * in the browser target). Subclasses can override `normalizeAction` to
120
+ * pre-process the action before calling the user handler.
121
+ */
122
+ onAction(actionName: string, handler: ActionHandler): void;
123
+ /**
124
+ * Platform hook: normalize an incoming action before the user handler
125
+ * sees it. Default identity; subclasses can override to unwrap native
126
+ * values (e.g. browser Maps in action payloads).
127
+ */
128
+ protected normalizeAction(action: Action): Action;
129
+ /**
130
+ * Initialize the primary module.
131
+ */
132
+ setModule(name: string, actions: string[], stateKeys: string[], initialState: Record<string, any>): void;
133
+ /**
134
+ * Register a named module for multi-module apps.
135
+ *
136
+ * Unlike setModule which sets the primary module, this registers an
137
+ * additional module whose state is scoped to `module <name> { ... }`
138
+ * blocks in the DSL.
139
+ */
140
+ registerModule(name: string, actions: string[], stateKeys: string[], initialState: Record<string, any>): void;
141
+ /**
142
+ * Get the current revision number.
143
+ *
144
+ * Note: the underlying WASM builder returns `bigint` in some targets
145
+ * and `number` in others; this normalizes to `number` for consumer
146
+ * ergonomics (revision counts don't exceed 2^53).
147
+ */
148
+ getRevision(): number;
149
+ /**
150
+ * Clear resolved components and caches, preserving primitives and resolver.
151
+ * Call before renderSource() during hot-reload so components are re-resolved
152
+ * from fresh source files.
153
+ */
154
+ clearResolvedComponents(): void;
155
+ /**
156
+ * Clear the engine tree.
157
+ */
158
+ clearTree(): void;
159
+ /**
160
+ * Full reset: clears tree, module, component registry, dependencies,
161
+ * and revision. Render callback and component resolver are preserved.
162
+ */
163
+ reset(): void;
164
+ /**
165
+ * Debug method to inspect parsed components.
166
+ */
167
+ debugParseComponent(source: string): string;
168
+ /**
169
+ * Set (or replace) a named data source context.
170
+ *
171
+ * Registers the provider in the dependency graph, stores the data,
172
+ * and re-renders every node bound to `$name.*`.
173
+ *
174
+ * @param name - Provider name (e.g., "spacetime", "firebase")
175
+ * @param data - Full state object for this provider
176
+ */
177
+ setContext(name: string, data: Record<string, unknown>): void;
178
+ /**
179
+ * Remove a data source context entirely.
180
+ * Drops the provider's state and re-renders bound nodes (they resolve to null).
181
+ */
182
+ removeContext(name: string): void;
183
+ /**
184
+ * Register resources (name → raw SVG string) with the engine.
185
+ *
186
+ * Each SVG is parsed by the WASM engine. When the engine encounters
187
+ * `Icon(@resources.heart)` in the DSL, it resolves the name from registered
188
+ * resources and injects SVG path data into the Create patch props.
189
+ *
190
+ * @param map - Flat map of resource name to raw SVG string
191
+ */
192
+ registerResources(map: Record<string, string>): void;
193
+ }