@hypen-space/core 0.4.3 → 0.4.11
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.
- package/README.md +1 -1
- package/dist/app.d.ts +79 -22
- package/dist/app.js +248 -155
- package/dist/app.js.map +5 -5
- package/dist/components/builtin.js +251 -158
- package/dist/components/builtin.js.map +6 -6
- package/dist/context.js +1 -1
- package/dist/context.js.map +1 -1
- package/dist/discovery.d.ts +1 -1
- package/dist/discovery.js +249 -156
- package/dist/discovery.js.map +6 -6
- package/dist/disposable.js +1 -1
- package/dist/disposable.js.map +1 -1
- package/dist/engine.browser.d.ts +6 -0
- package/dist/engine.browser.js +192 -5
- package/dist/engine.browser.js.map +5 -4
- package/dist/engine.d.ts +6 -0
- package/dist/engine.js +192 -5
- package/dist/engine.js.map +5 -4
- package/dist/events.js +1 -1
- package/dist/events.js.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.js +248 -155
- package/dist/index.browser.js.map +6 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.js +254 -158
- package/dist/index.js.map +7 -7
- package/dist/loader.js +1 -1
- package/dist/loader.js.map +1 -1
- package/dist/logger.js +245 -0
- package/dist/logger.js.map +10 -0
- package/dist/managed-router.d.ts +3 -4
- package/dist/plugin.js +1 -1
- package/dist/plugin.js.map +1 -1
- package/dist/remote/client.js +34 -2
- package/dist/remote/client.js.map +3 -3
- package/dist/remote/index.js +609 -163
- package/dist/remote/index.js.map +8 -7
- package/dist/remote/server.d.ts +46 -15
- package/dist/remote/server.js +609 -163
- package/dist/remote/server.js.map +8 -7
- package/dist/renderer.js +1 -1
- package/dist/renderer.js.map +1 -1
- package/dist/result.d.ts +18 -0
- package/dist/router.js +1 -1
- package/dist/router.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +2 -0
- package/dist/types.js.map +9 -0
- package/package.json +1 -1
- package/src/app.ts +162 -41
- package/src/components/builtin.ts +3 -4
- package/src/discovery.ts +2 -2
- package/src/engine.browser.ts +27 -4
- package/src/engine.ts +27 -4
- package/src/index.browser.ts +0 -2
- package/src/index.ts +3 -2
- package/src/managed-router.ts +5 -6
- package/src/remote/server.ts +116 -21
- package/src/result.ts +48 -0
- package/src/types.ts +1 -1
- package/wasm-browser/hypen_engine.d.ts +3 -3
- package/wasm-browser/hypen_engine.js +73 -66
- package/wasm-browser/hypen_engine_bg.wasm +0 -0
- package/wasm-browser/hypen_engine_bg.wasm.d.ts +3 -3
- package/wasm-browser/package.json +1 -1
- package/wasm-node/hypen_engine.js +74 -66
- package/wasm-node/hypen_engine_bg.wasm +0 -0
- package/wasm-node/hypen_engine_bg.wasm.d.ts +3 -3
- package/wasm-node/package.json +1 -1
- package/dist/module-registry.d.ts +0 -42
- package/src/module-registry.ts +0 -76
package/dist/renderer.js.map
CHANGED
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
"/**\n * Renderer abstraction interface\n *\n * Renderers are pluggable and can be implemented for different platforms\n * (DOM, Canvas, Native, etc.)\n */\n\nimport type { Patch } from \"./types.js\";\nimport { frameworkLoggers } from \"./logger.js\";\n\nconst log = frameworkLoggers.renderer;\n\n/**\n * Renderer interface that all platform renderers must implement\n */\nexport interface Renderer {\n /**\n * Apply a batch of patches to the render tree\n */\n applyPatches(patches: Patch[]): void;\n\n /**\n * Get a node by its ID (optional, for debugging)\n */\n getNode?(id: string): any;\n\n /**\n * Clear the entire render tree\n */\n clear?(): void;\n}\n\n/**\n * Base renderer class with common utilities\n */\nexport abstract class BaseRenderer implements Renderer {\n protected nodes: Map<string, any> = new Map();\n\n abstract applyPatches(patches: Patch[]): void;\n\n getNode(id: string): any {\n return this.nodes.get(id);\n }\n\n clear(): void {\n this.nodes.clear();\n }\n\n /**\n * Apply a single patch\n */\n protected applyPatch(patch: Patch): void {\n switch (patch.type) {\n case \"create\":\n this.onCreate(patch.id!, patch.elementType!, patch.props || {});\n break;\n case \"setProp\":\n this.onSetProp(patch.id!, patch.name!, patch.value);\n break;\n case \"setText\":\n this.onSetText(patch.id!, patch.text!);\n break;\n case \"insert\":\n this.onInsert(patch.parentId!, patch.id!, patch.beforeId);\n break;\n case \"move\":\n this.onMove(patch.parentId!, patch.id!, patch.beforeId);\n break;\n case \"remove\":\n this.onRemove(patch.id!);\n break;\n case \"attachEvent\":\n this.onAttachEvent(patch.id!, patch.eventName!);\n break;\n case \"detachEvent\":\n this.onDetachEvent(patch.id!, patch.eventName!);\n break;\n }\n }\n\n /**\n * Platform-specific patch handlers\n */\n protected abstract onCreate(id: string, elementType: string, props: Record<string, any>): void;\n protected abstract onSetProp(id: string, name: string, value: any): void;\n protected abstract onSetText(id: string, text: string): void;\n protected abstract onInsert(parentId: string, id: string, beforeId?: string): void;\n protected abstract onMove(parentId: string, id: string, beforeId?: string): void;\n protected abstract onRemove(id: string): void;\n protected abstract onAttachEvent(id: string, eventName: string): void;\n protected abstract onDetachEvent(id: string, eventName: string): void;\n}\n\n/**\n * Console/Debug renderer that logs patches\n */\nexport class ConsoleRenderer implements Renderer {\n applyPatches(patches: Patch[]): void {\n console.group(\"Hypen Patches\");\n for (const patch of patches) {\n console.log(patch);\n }\n console.groupEnd();\n }\n}\n"
|
|
7
7
|
],
|
|
8
8
|
"mappings": "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",
|
|
9
|
-
"debugId": "
|
|
9
|
+
"debugId": "FCB7787E6FDE288364756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/dist/result.d.ts
CHANGED
|
@@ -114,3 +114,21 @@ export declare class StateError extends HypenError {
|
|
|
114
114
|
readonly path?: string;
|
|
115
115
|
constructor(message: string, path?: string, cause?: unknown);
|
|
116
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Error thrown when parsing Hypen DSL source fails
|
|
119
|
+
*/
|
|
120
|
+
export declare class ParseError extends HypenError {
|
|
121
|
+
readonly source?: string;
|
|
122
|
+
constructor(message: string, source?: string, cause?: unknown);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Error thrown when rendering fails
|
|
126
|
+
*/
|
|
127
|
+
export declare class RenderError extends HypenError {
|
|
128
|
+
constructor(message: string, cause?: unknown);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Classify a WASM engine error string into the appropriate HypenError subclass.
|
|
132
|
+
* The engine returns JsValue error strings with known prefixes.
|
|
133
|
+
*/
|
|
134
|
+
export declare function classifyEngineError(err: unknown): HypenError;
|
package/dist/router.js
CHANGED
package/dist/router.js.map
CHANGED
|
@@ -7,6 +7,6 @@
|
|
|
7
7
|
"/**\n * Hypen Router - Declarative routing system\n * Integrated with Hypen's reactive state management\n */\n\nimport { createObservableState, getStateSnapshot } from \"./state.js\";\nimport { frameworkLoggers } from \"./logger.js\";\n\nconst log = frameworkLoggers.router;\n\nexport type RouteMatch = {\n params: Record<string, string>;\n query: Record<string, string>;\n path: string;\n};\n\nexport type RouteState = {\n currentPath: string;\n params: Record<string, string>;\n query: Record<string, string>;\n previousPath: string | null;\n};\n\nexport type RouteChangeCallback = (route: RouteState) => void;\n\n/**\n * Hypen Router - Manages application routing with pattern matching\n */\nexport class HypenRouter {\n private state: RouteState;\n private subscribers = new Set<RouteChangeCallback>();\n private isInitialized = false;\n private isUpdating = false;\n\n constructor() {\n // Create observable state for reactivity\n this.state = createObservableState<RouteState>(\n {\n currentPath: \"/\",\n params: {},\n query: {},\n previousPath: null,\n },\n {\n onChange: () => {\n this.notifySubscribers();\n },\n }\n );\n\n // Initialize from browser if available\n if (typeof window !== \"undefined\") {\n this.initializeBrowserSync();\n }\n }\n\n /**\n * Initialize browser history sync\n */\n private initializeBrowserSync() {\n // Get initial path from hash or pathname\n const initialPath = this.getPathFromBrowser();\n this.state.currentPath = initialPath;\n this.state.params = {};\n this.state.query = this.parseQuery();\n\n // Listen for browser back/forward\n window.addEventListener(\"popstate\", () => {\n const newPath = this.getPathFromBrowser();\n this.updatePath(newPath, false); // Don't push to history again\n });\n\n // Listen for hash changes\n window.addEventListener(\"hashchange\", () => {\n // Don't respond to hashchange events we triggered ourselves\n if (this.isUpdating) return;\n const newPath = this.getPathFromBrowser();\n this.updatePath(newPath, false);\n });\n\n this.isInitialized = true;\n log.debug(\"Router initialized at:\", initialPath);\n }\n\n /**\n * Get path from browser URL (supports both hash and pathname)\n */\n private getPathFromBrowser(): string {\n if (typeof window === \"undefined\") return \"/\";\n\n // Prefer hash-based routing for simplicity\n const hash = window.location.hash.slice(1);\n if (hash) return hash;\n\n // Fallback to pathname\n return window.location.pathname;\n }\n\n /**\n * Parse query string from URL\n */\n private parseQuery(): Record<string, string> {\n if (typeof window === \"undefined\") return {};\n\n const query: Record<string, string> = {};\n const searchParams = new URLSearchParams(window.location.search);\n\n searchParams.forEach((value, key) => {\n query[key] = value;\n });\n\n return query;\n }\n\n /**\n * Navigate to a new path\n */\n push(path: string) {\n log.debug(\"push:\", path);\n this.updatePath(path, true);\n }\n\n /**\n * Replace current path without adding to history\n */\n replace(path: string) {\n log.debug(\"replace:\", path);\n this.updatePath(path, true, true);\n }\n\n /**\n * Go back in history\n */\n back() {\n log.debug(\"back\");\n if (typeof window !== \"undefined\") {\n window.history.back();\n }\n }\n\n /**\n * Go forward in history\n */\n forward() {\n log.debug(\"forward\");\n if (typeof window !== \"undefined\") {\n window.history.forward();\n }\n }\n\n /**\n * Update the current path\n */\n private updatePath(\n path: string,\n updateBrowser: boolean,\n replace: boolean = false\n ) {\n // Prevent re-entrant updates\n if (this.isUpdating) return;\n\n this.isUpdating = true;\n try {\n const oldPath = this.state.currentPath;\n this.state.previousPath = oldPath;\n this.state.currentPath = path;\n this.state.query = this.parseQuery();\n\n // Notify subscribers synchronously before any browser events\n this.notifySubscribers();\n\n // Update browser URL if needed\n if (updateBrowser && typeof window !== \"undefined\") {\n const url = \"#\" + path;\n if (replace) {\n window.history.replaceState(null, \"\", url);\n } else {\n window.history.pushState(null, \"\", url);\n }\n\n // Manually trigger hashchange event\n const hashChangeEvent = new HashChangeEvent(\"hashchange\", {\n oldURL: window.location.href.replace(window.location.hash, \"#\" + oldPath),\n newURL: window.location.href,\n });\n window.dispatchEvent(hashChangeEvent);\n }\n } finally {\n this.isUpdating = false;\n }\n }\n\n /**\n * Get current path\n */\n getCurrentPath(): string {\n return this.state.currentPath;\n }\n\n /**\n * Get current route params\n */\n getParams(): Record<string, string> {\n return { ...this.state.params };\n }\n\n /**\n * Get current query params\n */\n getQuery(): Record<string, string> {\n return { ...this.state.query };\n }\n\n /**\n * Get full route state snapshot\n */\n getState(): RouteState {\n return getStateSnapshot(this.state);\n }\n\n /**\n * Match a pattern against a path\n */\n matchPath(pattern: string, path: string): RouteMatch | null {\n // Handle invalid inputs gracefully\n if (!pattern || typeof pattern !== 'string') {\n return null;\n }\n if (!path || typeof path !== 'string') {\n return null;\n }\n\n // Exact match\n if (pattern === path) {\n return {\n params: {},\n query: this.state.query,\n path,\n };\n }\n\n // Wildcard match: /dashboard/* matches /dashboard/anything\n if (pattern.endsWith(\"/*\")) {\n const prefix = pattern.slice(0, -2);\n if (path === prefix || path.startsWith(prefix + \"/\")) {\n return {\n params: {},\n query: this.state.query,\n path,\n };\n }\n return null;\n }\n\n // Parameter match: /users/:id matches /users/123\n const paramNames: string[] = [];\n const regexPattern = pattern\n .replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, (_, name) => {\n paramNames.push(name);\n return \"([^/]+)\";\n })\n .replace(/\\*/g, \".*\");\n\n const regex = new RegExp(`^${regexPattern}$`);\n const match = path.match(regex);\n\n if (!match) return null;\n\n // Extract params\n const params: Record<string, string> = {};\n paramNames.forEach((name, i) => {\n const value = match[i + 1];\n if (value !== undefined) {\n params[name] = decodeURIComponent(value);\n }\n });\n\n return {\n params,\n query: this.state.query,\n path,\n };\n }\n\n /**\n * Subscribe to route changes\n */\n onNavigate(callback: RouteChangeCallback): () => void {\n this.subscribers.add(callback);\n\n // Call immediately with current state\n try {\n callback(this.getState());\n } catch (error) {\n log.error(\"Error in route subscriber:\", error);\n }\n\n // Return unsubscribe function\n return () => {\n this.subscribers.delete(callback);\n };\n }\n\n /**\n * Notify all subscribers of route change\n */\n private notifySubscribers() {\n const routeState = this.getState();\n this.subscribers.forEach((callback) => {\n try {\n callback(routeState);\n } catch (error) {\n log.error(\"Error in route subscriber:\", error);\n }\n });\n }\n\n /**\n * Check if a path matches the current route\n */\n isActive(pattern: string): boolean {\n return this.matchPath(pattern, this.state.currentPath) !== null;\n }\n\n /**\n * Get a URL with query params\n */\n buildUrl(path: string, query?: Record<string, string>): string {\n if (!query || Object.keys(query).length === 0) {\n return path;\n }\n\n const queryString = new URLSearchParams(query).toString();\n return `${path}?${queryString}`;\n }\n}\n"
|
|
8
8
|
],
|
|
9
9
|
"mappings": "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",
|
|
10
|
-
"debugId": "
|
|
10
|
+
"debugId": "00FB5513845955B364756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* packages can import them without pulling in any WASM code.
|
|
6
6
|
*/
|
|
7
7
|
export type Patch = {
|
|
8
|
-
type: "create" | "setProp" | "setText" | "insert" | "move" | "remove" | "attachEvent" | "detachEvent";
|
|
8
|
+
type: "create" | "setProp" | "removeProp" | "setText" | "insert" | "move" | "remove" | "attachEvent" | "detachEvent";
|
|
9
9
|
id?: string;
|
|
10
10
|
elementType?: string;
|
|
11
11
|
props?: Record<string, any>;
|
package/dist/types.js
ADDED
package/package.json
CHANGED
package/src/app.ts
CHANGED
|
@@ -21,22 +21,12 @@ import { createLogger } from "./logger.js";
|
|
|
21
21
|
|
|
22
22
|
const log = createLogger("ModuleInstance");
|
|
23
23
|
|
|
24
|
-
export type
|
|
25
|
-
root: HypenRouter;
|
|
26
|
-
current?: HypenRouter;
|
|
27
|
-
parent?: HypenRouter;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export type ActionContext = {
|
|
24
|
+
export type ActionContext<P = unknown> = {
|
|
31
25
|
name: string;
|
|
32
|
-
payload?:
|
|
26
|
+
payload?: P;
|
|
33
27
|
sender?: string;
|
|
34
28
|
};
|
|
35
29
|
|
|
36
|
-
export type ActionNext = {
|
|
37
|
-
router: HypenRouter; // Direct access to router instance (from nearest parent)
|
|
38
|
-
};
|
|
39
|
-
|
|
40
30
|
export type GlobalContext = {
|
|
41
31
|
getModule: <T = unknown>(id: string) => ModuleReference<T>;
|
|
42
32
|
hasModule: (id: string) => boolean;
|
|
@@ -44,7 +34,7 @@ export type GlobalContext = {
|
|
|
44
34
|
getGlobalState: () => Record<string, unknown>;
|
|
45
35
|
emit: (event: string, payload?: unknown) => void;
|
|
46
36
|
on: (event: string, handler: (payload?: unknown) => void) => () => void;
|
|
47
|
-
|
|
37
|
+
router: HypenRouter | null;
|
|
48
38
|
};
|
|
49
39
|
|
|
50
40
|
export type LifecycleHandler<T> = (
|
|
@@ -55,17 +45,16 @@ export type LifecycleHandler<T> = (
|
|
|
55
45
|
/**
|
|
56
46
|
* Action handler context - all parameters available explicitly
|
|
57
47
|
*/
|
|
58
|
-
export interface ActionHandlerContext<T> {
|
|
59
|
-
action: ActionContext
|
|
48
|
+
export interface ActionHandlerContext<T, P = unknown> {
|
|
49
|
+
action: ActionContext<P>;
|
|
60
50
|
state: T;
|
|
61
|
-
next: ActionNext;
|
|
62
51
|
context: GlobalContext;
|
|
63
52
|
}
|
|
64
53
|
|
|
65
54
|
/**
|
|
66
55
|
* Action handler - receives all context in a single object
|
|
67
56
|
*/
|
|
68
|
-
export type ActionHandler<T> = (ctx: ActionHandlerContext<T>) => void | Promise<void>;
|
|
57
|
+
export type ActionHandler<T, P = unknown> = (ctx: ActionHandlerContext<T, P>) => void | Promise<void>;
|
|
69
58
|
|
|
70
59
|
/**
|
|
71
60
|
* Context passed to onDisconnect handler
|
|
@@ -152,7 +141,7 @@ export interface HypenModuleDefinition<T = unknown> {
|
|
|
152
141
|
template?: string;
|
|
153
142
|
handlers: {
|
|
154
143
|
onCreated?: LifecycleHandler<T>;
|
|
155
|
-
onAction: Map<string, ActionHandler<T>>;
|
|
144
|
+
onAction: Map<string, ActionHandler<T, any>>;
|
|
156
145
|
onDestroyed?: LifecycleHandler<T>;
|
|
157
146
|
/** Called when client disconnects (session persists for TTL) */
|
|
158
147
|
onDisconnect?: DisconnectHandler<T>;
|
|
@@ -177,20 +166,23 @@ export class HypenAppBuilder<T> {
|
|
|
177
166
|
private initialState: T;
|
|
178
167
|
private options: { persist?: boolean; version?: number; name?: string };
|
|
179
168
|
private createdHandler?: LifecycleHandler<T>;
|
|
180
|
-
private actionHandlers: Map<string, ActionHandler<T>> = new Map();
|
|
169
|
+
private actionHandlers: Map<string, ActionHandler<T, any>> = new Map();
|
|
181
170
|
private destroyedHandler?: LifecycleHandler<T>;
|
|
182
171
|
private disconnectHandler?: DisconnectHandler<T>;
|
|
183
172
|
private reconnectHandler?: ReconnectHandler<T>;
|
|
184
173
|
private expireHandler?: ExpireHandler;
|
|
185
174
|
private errorHandler?: ErrorHandler<T>;
|
|
186
175
|
private template?: string;
|
|
176
|
+
private _registry?: Map<string, HypenModuleDefinition>;
|
|
187
177
|
|
|
188
178
|
constructor(
|
|
189
179
|
initialState: T,
|
|
190
|
-
options?: { persist?: boolean; version?: number; name?: string }
|
|
180
|
+
options?: { persist?: boolean; version?: number; name?: string },
|
|
181
|
+
registry?: Map<string, HypenModuleDefinition>
|
|
191
182
|
) {
|
|
192
183
|
this.initialState = initialState;
|
|
193
184
|
this.options = options || {};
|
|
185
|
+
this._registry = registry;
|
|
194
186
|
}
|
|
195
187
|
|
|
196
188
|
/**
|
|
@@ -202,10 +194,24 @@ export class HypenAppBuilder<T> {
|
|
|
202
194
|
}
|
|
203
195
|
|
|
204
196
|
/**
|
|
205
|
-
* Register a handler for a specific action
|
|
197
|
+
* Register a handler for a specific action.
|
|
198
|
+
* Optionally provide a payload type parameter for typed action payloads.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* // Typed payload:
|
|
203
|
+
* .onAction<{ amount: number }>("add", ({ action, state }) => {
|
|
204
|
+
* action.payload.amount; // fully typed
|
|
205
|
+
* })
|
|
206
|
+
*
|
|
207
|
+
* // Untyped (payload is unknown):
|
|
208
|
+
* .onAction("add", ({ action, state }) => {
|
|
209
|
+
* action.payload; // unknown
|
|
210
|
+
* })
|
|
211
|
+
* ```
|
|
206
212
|
*/
|
|
207
|
-
onAction(name: string, fn: ActionHandler<T>): this {
|
|
208
|
-
this.actionHandlers.set(name, fn);
|
|
213
|
+
onAction<P = unknown>(name: string, fn: ActionHandler<T, P>): this {
|
|
214
|
+
this.actionHandlers.set(name, fn as ActionHandler<T, any>);
|
|
209
215
|
return this;
|
|
210
216
|
}
|
|
211
217
|
|
|
@@ -319,7 +325,7 @@ export class HypenAppBuilder<T> {
|
|
|
319
325
|
? Object.keys(this.initialState)
|
|
320
326
|
: [];
|
|
321
327
|
|
|
322
|
-
|
|
328
|
+
const definition: HypenModuleDefinition<T> = {
|
|
323
329
|
name: this.options.name,
|
|
324
330
|
actions: Array.from(this.actionHandlers.keys()),
|
|
325
331
|
stateKeys,
|
|
@@ -337,13 +343,27 @@ export class HypenAppBuilder<T> {
|
|
|
337
343
|
onError: this.errorHandler,
|
|
338
344
|
},
|
|
339
345
|
};
|
|
346
|
+
|
|
347
|
+
// Auto-register in the app registry when the module has a name
|
|
348
|
+
if (this.options.name && this._registry) {
|
|
349
|
+
this._registry.set(this.options.name, definition as HypenModuleDefinition);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return definition;
|
|
340
353
|
}
|
|
341
354
|
}
|
|
342
355
|
|
|
343
356
|
/**
|
|
344
|
-
* Hypen App API
|
|
357
|
+
* Hypen App API — singleton factory and component registry.
|
|
358
|
+
*
|
|
359
|
+
* Modules built with a `name` are automatically registered here.
|
|
360
|
+
* Consumers (ManagedRouter, RemoteServer, ComponentResolver) read from this
|
|
361
|
+
* registry instead of requiring a separate ModuleRegistry instance.
|
|
345
362
|
*/
|
|
346
363
|
export class HypenApp {
|
|
364
|
+
/** @internal */
|
|
365
|
+
readonly _registry = new Map<string, HypenModuleDefinition>();
|
|
366
|
+
|
|
347
367
|
/**
|
|
348
368
|
* Define the initial state for a module
|
|
349
369
|
*/
|
|
@@ -351,7 +371,83 @@ export class HypenApp {
|
|
|
351
371
|
initial: T,
|
|
352
372
|
options?: { persist?: boolean; version?: number; name?: string }
|
|
353
373
|
): HypenAppBuilder<T> {
|
|
354
|
-
return new HypenAppBuilder(initial, options);
|
|
374
|
+
return new HypenAppBuilder(initial, options, this._registry);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Convenience: start a module builder with a name pre-set.
|
|
379
|
+
*
|
|
380
|
+
* @example
|
|
381
|
+
* ```typescript
|
|
382
|
+
* export default app
|
|
383
|
+
* .module("Settings")
|
|
384
|
+
* .defineState({ theme: "dark" })
|
|
385
|
+
* .ui(hypen`...`);
|
|
386
|
+
* ```
|
|
387
|
+
*/
|
|
388
|
+
module(name: string) {
|
|
389
|
+
const registry = this._registry;
|
|
390
|
+
return {
|
|
391
|
+
defineState: <T>(
|
|
392
|
+
initial: T,
|
|
393
|
+
options?: { persist?: boolean; version?: number }
|
|
394
|
+
): HypenAppBuilder<T> => {
|
|
395
|
+
return new HypenAppBuilder(initial, { ...options, name }, registry);
|
|
396
|
+
},
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// ---------------------------------------------------------------------------
|
|
401
|
+
// Registry API
|
|
402
|
+
// ---------------------------------------------------------------------------
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Get a registered module definition by component name.
|
|
406
|
+
*/
|
|
407
|
+
get(name: string): HypenModuleDefinition | undefined {
|
|
408
|
+
return this._registry.get(name);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Check if a module definition is registered.
|
|
413
|
+
*/
|
|
414
|
+
has(name: string): boolean {
|
|
415
|
+
return this._registry.has(name);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Read-only view of all registered component definitions.
|
|
420
|
+
*/
|
|
421
|
+
get components(): ReadonlyMap<string, HypenModuleDefinition> {
|
|
422
|
+
return this._registry;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Get all registered component names.
|
|
427
|
+
*/
|
|
428
|
+
getNames(): string[] {
|
|
429
|
+
return Array.from(this._registry.keys());
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Number of registered definitions.
|
|
434
|
+
*/
|
|
435
|
+
get size(): number {
|
|
436
|
+
return this._registry.size;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Unregister a module definition.
|
|
441
|
+
*/
|
|
442
|
+
unregister(name: string): void {
|
|
443
|
+
this._registry.delete(name);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Clear all registered definitions.
|
|
448
|
+
*/
|
|
449
|
+
clear(): void {
|
|
450
|
+
this._registry.clear();
|
|
355
451
|
}
|
|
356
452
|
}
|
|
357
453
|
|
|
@@ -368,19 +464,19 @@ export class HypenModuleInstance<T extends object = any> {
|
|
|
368
464
|
private definition: HypenModuleDefinition<T>;
|
|
369
465
|
private state: T;
|
|
370
466
|
private isDestroyed = false;
|
|
371
|
-
private
|
|
467
|
+
private router: HypenRouter | null;
|
|
372
468
|
private globalContext?: HypenGlobalContext;
|
|
373
469
|
private stateChangeCallbacks: Array<() => void> = [];
|
|
374
470
|
|
|
375
471
|
constructor(
|
|
376
472
|
engine: IEngine,
|
|
377
473
|
definition: HypenModuleDefinition<T>,
|
|
378
|
-
|
|
474
|
+
router?: HypenRouter | null,
|
|
379
475
|
globalContext?: HypenGlobalContext
|
|
380
476
|
) {
|
|
381
477
|
this.engine = engine;
|
|
382
478
|
this.definition = definition;
|
|
383
|
-
this.
|
|
479
|
+
this.router = router ?? null;
|
|
384
480
|
this.globalContext = globalContext;
|
|
385
481
|
|
|
386
482
|
// Named state prefix — all lowercase per convention
|
|
@@ -425,10 +521,6 @@ export class HypenModuleInstance<T extends object = any> {
|
|
|
425
521
|
sender: action.sender,
|
|
426
522
|
};
|
|
427
523
|
|
|
428
|
-
const next: ActionNext = {
|
|
429
|
-
router: this.routerContext?.root || (null as any),
|
|
430
|
-
};
|
|
431
|
-
|
|
432
524
|
const context: GlobalContext | undefined = this.globalContext
|
|
433
525
|
? this.createGlobalContextAPI()
|
|
434
526
|
: undefined;
|
|
@@ -437,7 +529,6 @@ export class HypenModuleInstance<T extends object = any> {
|
|
|
437
529
|
const result = await this.executeAction(actionName, handler, {
|
|
438
530
|
action: actionCtx,
|
|
439
531
|
state: this.state,
|
|
440
|
-
next,
|
|
441
532
|
context: context!,
|
|
442
533
|
});
|
|
443
534
|
|
|
@@ -452,6 +543,22 @@ export class HypenModuleInstance<T extends object = any> {
|
|
|
452
543
|
});
|
|
453
544
|
}
|
|
454
545
|
|
|
546
|
+
// Auto-register __hypen_bind for .bind() two-way binding support
|
|
547
|
+
this.engine.onAction("__hypen_bind", (action: Action) => {
|
|
548
|
+
const payload = action.payload as { path?: string; value?: unknown } | null;
|
|
549
|
+
if (!payload?.path) return;
|
|
550
|
+
|
|
551
|
+
const segments = payload.path.split(".");
|
|
552
|
+
let target: any = this.state;
|
|
553
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
554
|
+
const seg = segments[i]!;
|
|
555
|
+
target = target?.[seg];
|
|
556
|
+
if (target == null) return;
|
|
557
|
+
}
|
|
558
|
+
const lastSeg = segments[segments.length - 1]!;
|
|
559
|
+
target[lastSeg] = payload.value;
|
|
560
|
+
});
|
|
561
|
+
|
|
455
562
|
// Call onCreated
|
|
456
563
|
this.callCreatedHandler();
|
|
457
564
|
}
|
|
@@ -473,12 +580,10 @@ export class HypenModuleInstance<T extends object = any> {
|
|
|
473
580
|
emit: (event: string, payload?: any) => ctx.emit(event, payload),
|
|
474
581
|
on: (event: string, handler: (payload?: any) => void) =>
|
|
475
582
|
ctx.on(event, handler),
|
|
583
|
+
router: this.router,
|
|
476
584
|
};
|
|
477
585
|
|
|
478
|
-
// Expose
|
|
479
|
-
if ((ctx as any).__router) {
|
|
480
|
-
api.__router = (ctx as any).__router;
|
|
481
|
-
}
|
|
586
|
+
// Expose hypen engine for built-in components (if available)
|
|
482
587
|
if ((ctx as any).__hypenEngine) {
|
|
483
588
|
(api as any).__hypenEngine = (ctx as any).__hypenEngine;
|
|
484
589
|
}
|
|
@@ -492,7 +597,7 @@ export class HypenModuleInstance<T extends object = any> {
|
|
|
492
597
|
*/
|
|
493
598
|
private async executeAction(
|
|
494
599
|
actionName: string,
|
|
495
|
-
handler: ActionHandler<T>,
|
|
600
|
+
handler: ActionHandler<T, any>,
|
|
496
601
|
ctx: ActionHandlerContext<T>
|
|
497
602
|
): Promise<Result<void, ActionError>> {
|
|
498
603
|
try {
|
|
@@ -575,7 +680,15 @@ export class HypenModuleInstance<T extends object = any> {
|
|
|
575
680
|
private async callCreatedHandler(): Promise<void> {
|
|
576
681
|
if (this.definition.handlers.onCreated) {
|
|
577
682
|
const context = this.globalContext ? this.createGlobalContextAPI() : undefined;
|
|
578
|
-
|
|
683
|
+
try {
|
|
684
|
+
await this.definition.handlers.onCreated(this.state, context);
|
|
685
|
+
} catch (e) {
|
|
686
|
+
const error = e instanceof HypenError ? e : new ActionError("onCreated", e);
|
|
687
|
+
const shouldRethrow = await this.handleError(error, { lifecycle: "created" });
|
|
688
|
+
if (shouldRethrow) {
|
|
689
|
+
throw error;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
579
692
|
}
|
|
580
693
|
}
|
|
581
694
|
|
|
@@ -593,7 +706,15 @@ export class HypenModuleInstance<T extends object = any> {
|
|
|
593
706
|
if (this.isDestroyed) return;
|
|
594
707
|
|
|
595
708
|
if (this.definition.handlers.onDestroyed) {
|
|
596
|
-
|
|
709
|
+
try {
|
|
710
|
+
await this.definition.handlers.onDestroyed(this.state);
|
|
711
|
+
} catch (e) {
|
|
712
|
+
const error = e instanceof HypenError ? e : new ActionError("onDestroyed", e);
|
|
713
|
+
const shouldRethrow = await this.handleError(error, { lifecycle: "destroyed" });
|
|
714
|
+
if (shouldRethrow) {
|
|
715
|
+
throw error;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
597
718
|
}
|
|
598
719
|
|
|
599
720
|
this.isDestroyed = true;
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { app } from "../app.js";
|
|
7
|
-
import type { HypenRouter } from "../router.js";
|
|
8
7
|
import { frameworkLoggers } from "../logger.js";
|
|
9
8
|
|
|
10
9
|
const log = frameworkLoggers.router;
|
|
@@ -36,7 +35,7 @@ export const Router = app
|
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
// Subscribe to router changes
|
|
39
|
-
const router =
|
|
38
|
+
const router = context.router;
|
|
40
39
|
if (!router) {
|
|
41
40
|
log.error("Router not found in context");
|
|
42
41
|
return;
|
|
@@ -149,7 +148,7 @@ export const Link = app
|
|
|
149
148
|
{ name: "__Link" }
|
|
150
149
|
)
|
|
151
150
|
.onAction("navigate", ({ state, context }) => {
|
|
152
|
-
const router =
|
|
151
|
+
const router = context?.router;
|
|
153
152
|
if (!router) {
|
|
154
153
|
log.error("Link requires router context");
|
|
155
154
|
return;
|
|
@@ -162,7 +161,7 @@ export const Link = app
|
|
|
162
161
|
if (!context) return;
|
|
163
162
|
|
|
164
163
|
// Check if current path matches this link's target
|
|
165
|
-
const router =
|
|
164
|
+
const router = context.router;
|
|
166
165
|
if (router) {
|
|
167
166
|
router.onNavigate((routeState) => {
|
|
168
167
|
state.isActive = routeState.currentPath === state.to;
|
package/src/discovery.ts
CHANGED
|
@@ -43,7 +43,7 @@ export interface DiscoveryOptions {
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Recursively scan subdirectories
|
|
46
|
-
* Default:
|
|
46
|
+
* Default: true
|
|
47
47
|
*/
|
|
48
48
|
recursive?: boolean;
|
|
49
49
|
|
|
@@ -95,7 +95,7 @@ export async function discoverComponents(
|
|
|
95
95
|
): Promise<DiscoveredComponent[]> {
|
|
96
96
|
const {
|
|
97
97
|
patterns = ["single-file", "folder", "sibling", "index"],
|
|
98
|
-
recursive =
|
|
98
|
+
recursive = true,
|
|
99
99
|
debug = false,
|
|
100
100
|
} = options;
|
|
101
101
|
|
package/src/engine.browser.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { frameworkLoggers } from "./logger.js";
|
|
7
|
+
import { classifyEngineError } from "./result.js";
|
|
7
8
|
import type { Patch, Action, RenderCallback, ActionHandler, ResolvedComponent, ComponentResolver } from "./types.js";
|
|
8
9
|
|
|
9
10
|
// Re-export types so existing consumers of "./engine.browser.js" still work
|
|
@@ -125,10 +126,16 @@ export class Engine {
|
|
|
125
126
|
|
|
126
127
|
/**
|
|
127
128
|
* Parse and render Hypen DSL source code
|
|
129
|
+
* @throws {ParseError} if the source fails to parse
|
|
130
|
+
* @throws {RenderError} if rendering fails
|
|
128
131
|
*/
|
|
129
132
|
renderSource(source: string): void {
|
|
130
133
|
const engine = this.ensureInitialized();
|
|
131
|
-
|
|
134
|
+
try {
|
|
135
|
+
engine.renderSource(source);
|
|
136
|
+
} catch (err) {
|
|
137
|
+
throw classifyEngineError(err);
|
|
138
|
+
}
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
/**
|
|
@@ -141,15 +148,22 @@ export class Engine {
|
|
|
141
148
|
|
|
142
149
|
/**
|
|
143
150
|
* Render a component into a specific parent node (subtree rendering)
|
|
151
|
+
* @throws {ParseError} if the source fails to parse
|
|
152
|
+
* @throws {RenderError} if the parent node is not found or rendering fails
|
|
144
153
|
*/
|
|
145
154
|
renderInto(source: string, parentNodeId: string, state: Record<string, any>): void {
|
|
146
155
|
const engine = this.ensureInitialized();
|
|
147
156
|
const safeState = JSON.parse(JSON.stringify(state));
|
|
148
|
-
|
|
157
|
+
try {
|
|
158
|
+
engine.renderInto(source, parentNodeId, safeState);
|
|
159
|
+
} catch (err) {
|
|
160
|
+
throw classifyEngineError(err);
|
|
161
|
+
}
|
|
149
162
|
}
|
|
150
163
|
|
|
151
164
|
/**
|
|
152
165
|
* Notify the engine of state changes using sparse updates
|
|
166
|
+
* @throws {StateError} if the state patch is invalid
|
|
153
167
|
*/
|
|
154
168
|
notifyStateChange(paths: string[], values: Record<string, any>): void {
|
|
155
169
|
const engine = this.ensureInitialized();
|
|
@@ -159,7 +173,11 @@ export class Engine {
|
|
|
159
173
|
}
|
|
160
174
|
|
|
161
175
|
const plainValues = JSON.parse(JSON.stringify(values));
|
|
162
|
-
|
|
176
|
+
try {
|
|
177
|
+
engine.updateStateSparse(paths, plainValues);
|
|
178
|
+
} catch (err) {
|
|
179
|
+
throw classifyEngineError(err);
|
|
180
|
+
}
|
|
163
181
|
log.debug("State changed (sparse):", paths);
|
|
164
182
|
}
|
|
165
183
|
|
|
@@ -189,11 +207,16 @@ export class Engine {
|
|
|
189
207
|
|
|
190
208
|
/**
|
|
191
209
|
* Dispatch an action
|
|
210
|
+
* @throws {HypenError} if the action dispatch fails
|
|
192
211
|
*/
|
|
193
212
|
dispatchAction(name: string, payload?: any): void {
|
|
194
213
|
const engine = this.ensureInitialized();
|
|
195
214
|
log.debug(`Action dispatched: ${name}`);
|
|
196
|
-
|
|
215
|
+
try {
|
|
216
|
+
engine.dispatchAction(name, payload ?? null);
|
|
217
|
+
} catch (err) {
|
|
218
|
+
throw classifyEngineError(err);
|
|
219
|
+
}
|
|
197
220
|
}
|
|
198
221
|
|
|
199
222
|
/**
|