@hypen-space/core 0.2.0

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 (49) hide show
  1. package/dist/chunk-5va59f7m.js +22 -0
  2. package/dist/chunk-5va59f7m.js.map +9 -0
  3. package/dist/engine.d.ts +101 -0
  4. package/dist/events.d.ts +78 -0
  5. package/dist/index.browser.d.ts +13 -0
  6. package/dist/index.d.ts +33 -0
  7. package/dist/remote/index.d.ts +6 -0
  8. package/dist/router.d.ts +93 -0
  9. package/dist/src/app.js +160 -0
  10. package/dist/src/app.js.map +10 -0
  11. package/dist/src/context.js +114 -0
  12. package/dist/src/context.js.map +10 -0
  13. package/dist/src/engine.browser.js +130 -0
  14. package/dist/src/engine.browser.js.map +10 -0
  15. package/dist/src/engine.js +101 -0
  16. package/dist/src/engine.js.map +10 -0
  17. package/dist/src/events.js +72 -0
  18. package/dist/src/events.js.map +10 -0
  19. package/dist/src/index.browser.js +51 -0
  20. package/dist/src/index.browser.js.map +9 -0
  21. package/dist/src/index.js +55 -0
  22. package/dist/src/index.js.map +9 -0
  23. package/dist/src/remote/client.js +176 -0
  24. package/dist/src/remote/client.js.map +10 -0
  25. package/dist/src/remote/index.js +9 -0
  26. package/dist/src/remote/index.js.map +9 -0
  27. package/dist/src/remote/types.js +2 -0
  28. package/dist/src/remote/types.js.map +9 -0
  29. package/dist/src/renderer.js +58 -0
  30. package/dist/src/renderer.js.map +10 -0
  31. package/dist/src/router.js +189 -0
  32. package/dist/src/router.js.map +10 -0
  33. package/dist/src/state.js +226 -0
  34. package/dist/src/state.js.map +10 -0
  35. package/dist/state.d.ts +30 -0
  36. package/package.json +124 -0
  37. package/src/app.ts +330 -0
  38. package/src/context.ts +201 -0
  39. package/src/engine.browser.ts +245 -0
  40. package/src/engine.ts +208 -0
  41. package/src/events.ts +126 -0
  42. package/src/index.browser.ts +104 -0
  43. package/src/index.ts +126 -0
  44. package/src/remote/client.ts +274 -0
  45. package/src/remote/index.ts +17 -0
  46. package/src/remote/types.ts +51 -0
  47. package/src/renderer.ts +102 -0
  48. package/src/router.ts +311 -0
  49. package/src/state.ts +363 -0
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/context.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Global Context - Cross-module communication and state access\n */\n\nimport type { HypenModuleInstance } from \"./app.js\";\nimport { getStateSnapshot } from \"./state.js\";\nimport { TypedEventEmitter, type HypenFrameworkEvents } from \"./events.js\";\n\nexport type ModuleReference<T = unknown> = {\n state: T; // Live proxy state\n setState: (patch: Partial<T>) => void;\n getState: () => T; // Snapshot\n};\n\n/**\n * @deprecated Use TypedEventEmitter from events.ts for type-safe events\n */\nexport type EventHandler = (payload?: unknown) => void;\n\n/**\n * Global Context - Provides access to all modules and cross-module communication\n *\n * @template TEvents - Custom event map (extends HypenFrameworkEvents)\n */\nexport class HypenGlobalContext<TEvents extends Record<string, unknown> = HypenFrameworkEvents> {\n private modules = new Map<string, HypenModuleInstance>();\n private typedEvents: TypedEventEmitter<TEvents>;\n\n /**\n * @deprecated Legacy event bus for backward compatibility\n */\n private legacyEventBus = new Map<string, Set<EventHandler>>();\n\n constructor() {\n this.typedEvents = new TypedEventEmitter<TEvents>();\n }\n\n /**\n * Get the typed event emitter for type-safe event handling\n */\n get events(): TypedEventEmitter<TEvents> {\n return this.typedEvents;\n }\n\n /**\n * Register a module instance with an ID\n */\n registerModule(id: string, instance: HypenModuleInstance) {\n if (this.modules.has(id)) {\n console.warn(`Module \"${id}\" is already registered. Overwriting.`);\n }\n this.modules.set(id, instance);\n console.log(`Registered module: ${id}`);\n }\n\n /**\n * Unregister a module\n */\n unregisterModule(id: string) {\n this.modules.delete(id);\n console.log(`Unregistered module: ${id}`);\n }\n\n /**\n * Get a module by ID with type safety\n */\n getModule<T = unknown>(id: string): ModuleReference<T> {\n const module = this.modules.get(id);\n if (!module) {\n throw new Error(\n `Module \"${id}\" not found. Available modules: ${Array.from(this.modules.keys()).join(\", \")}`\n );\n }\n\n return {\n state: module.getLiveState() as T,\n setState: (patch: Partial<T>) => module.updateState(patch),\n getState: () => module.getState() as T,\n };\n }\n\n /**\n * Check if a module exists\n */\n hasModule(id: string): boolean {\n return this.modules.has(id);\n }\n\n /**\n * Get all registered module IDs\n */\n getModuleIds(): string[] {\n return Array.from(this.modules.keys());\n }\n\n /**\n * Get the entire app state tree (snapshot)\n */\n getGlobalState(): Record<string, unknown> {\n const state: Record<string, unknown> = {};\n this.modules.forEach((module, id) => {\n state[id] = module.getState();\n });\n return state;\n }\n\n /**\n * Emit an event to the event bus (legacy API for backward compatibility)\n * @deprecated Use `context.events.emit()` for type-safe events\n */\n emit(event: string, payload?: unknown): void {\n const handlers = this.legacyEventBus.get(event);\n if (!handlers || handlers.size === 0) {\n console.log(`Event \"${event}\" emitted but no listeners`);\n } else {\n console.log(`Emitting event: ${event}`, payload);\n handlers.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n console.error(`Error in event handler for \"${event}\":`, error);\n }\n });\n }\n\n // Also emit to typed event system if the event is registered there\n if (this.typedEvents.listenerCount(event as keyof TEvents) > 0) {\n this.typedEvents.emit(event as keyof TEvents, payload as TEvents[keyof TEvents]);\n }\n }\n\n /**\n * Subscribe to an event (legacy API for backward compatibility)\n * @deprecated Use `context.events.on()` for type-safe events\n */\n on(event: string, handler: EventHandler): () => void {\n if (!this.legacyEventBus.has(event)) {\n this.legacyEventBus.set(event, new Set());\n }\n\n const handlers = this.legacyEventBus.get(event)!;\n handlers.add(handler);\n\n console.log(`Listening to event: ${event}`);\n\n // Return unsubscribe function\n return () => {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this.legacyEventBus.delete(event);\n }\n };\n }\n\n /**\n * Unsubscribe from an event (legacy API)\n * @deprecated Use the unsubscribe function returned by `context.events.on()`\n */\n off(event: string, handler: EventHandler): void {\n const handlers = this.legacyEventBus.get(event);\n if (handlers) {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this.legacyEventBus.delete(event);\n }\n }\n }\n\n /**\n * Clear all event listeners for an event (legacy API)\n * @deprecated Use `context.events.removeAllListeners()`\n */\n clearEvent(event: string): void {\n this.legacyEventBus.delete(event);\n }\n\n /**\n * Clear all event listeners (legacy API)\n * @deprecated Use `context.events.clearAll()`\n */\n clearAllEvents(): void {\n this.legacyEventBus.clear();\n }\n\n /**\n * Get debug info about the context\n */\n debug(): {\n modules: string[];\n events: string[];\n typedEvents: Array<keyof TEvents>;\n state: Record<string, unknown>;\n } {\n return {\n modules: this.getModuleIds(),\n events: Array.from(this.legacyEventBus.keys()),\n typedEvents: this.typedEvents.eventNames(),\n state: this.getGlobalState(),\n };\n }\n}\n"
6
+ ],
7
+ "mappings": ";;;;;;AAwBO,MAAM,mBAAmF;AAAA,EACtF,UAAU,IAAI;AAAA,EACd;AAAA,EAKA,iBAAiB,IAAI;AAAA,EAE7B,WAAW,GAAG;AAAA,IACZ,KAAK,cAAc,IAAI;AAAA;AAAA,MAMrB,MAAM,GAA+B;AAAA,IACvC,OAAO,KAAK;AAAA;AAAA,EAMd,cAAc,CAAC,IAAY,UAA+B;AAAA,IACxD,IAAI,KAAK,QAAQ,IAAI,EAAE,GAAG;AAAA,MACxB,QAAQ,KAAK,WAAW,yCAAyC;AAAA,IACnE;AAAA,IACA,KAAK,QAAQ,IAAI,IAAI,QAAQ;AAAA,IAC7B,QAAQ,IAAI,sBAAsB,IAAI;AAAA;AAAA,EAMxC,gBAAgB,CAAC,IAAY;AAAA,IAC3B,KAAK,QAAQ,OAAO,EAAE;AAAA,IACtB,QAAQ,IAAI,wBAAwB,IAAI;AAAA;AAAA,EAM1C,SAAsB,CAAC,IAAgC;AAAA,IACrD,MAAM,SAAS,KAAK,QAAQ,IAAI,EAAE;AAAA,IAClC,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MACR,WAAW,qCAAqC,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC,EAAE,KAAK,IAAI,GAC3F;AAAA,IACF;AAAA,IAEA,OAAO;AAAA,MACL,OAAO,OAAO,aAAa;AAAA,MAC3B,UAAU,CAAC,UAAsB,OAAO,YAAY,KAAK;AAAA,MACzD,UAAU,MAAM,OAAO,SAAS;AAAA,IAClC;AAAA;AAAA,EAMF,SAAS,CAAC,IAAqB;AAAA,IAC7B,OAAO,KAAK,QAAQ,IAAI,EAAE;AAAA;AAAA,EAM5B,YAAY,GAAa;AAAA,IACvB,OAAO,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA;AAAA,EAMvC,cAAc,GAA4B;AAAA,IACxC,MAAM,QAAiC,CAAC;AAAA,IACxC,KAAK,QAAQ,QAAQ,CAAC,QAAQ,OAAO;AAAA,MACnC,MAAM,MAAM,OAAO,SAAS;AAAA,KAC7B;AAAA,IACD,OAAO;AAAA;AAAA,EAOT,IAAI,CAAC,OAAe,SAAyB;AAAA,IAC3C,MAAM,WAAW,KAAK,eAAe,IAAI,KAAK;AAAA,IAC9C,IAAI,CAAC,YAAY,SAAS,SAAS,GAAG;AAAA,MACpC,QAAQ,IAAI,UAAU,iCAAiC;AAAA,IACzD,EAAO;AAAA,MACL,QAAQ,IAAI,mBAAmB,SAAS,OAAO;AAAA,MAC/C,SAAS,QAAQ,CAAC,YAAY;AAAA,QAC5B,IAAI;AAAA,UACF,QAAQ,OAAO;AAAA,UACf,OAAO,OAAO;AAAA,UACd,QAAQ,MAAM,+BAA+B,WAAW,KAAK;AAAA;AAAA,OAEhE;AAAA;AAAA,IAIH,IAAI,KAAK,YAAY,cAAc,KAAsB,IAAI,GAAG;AAAA,MAC9D,KAAK,YAAY,KAAK,OAAwB,OAAiC;AAAA,IACjF;AAAA;AAAA,EAOF,EAAE,CAAC,OAAe,SAAmC;AAAA,IACnD,IAAI,CAAC,KAAK,eAAe,IAAI,KAAK,GAAG;AAAA,MACnC,KAAK,eAAe,IAAI,OAAO,IAAI,GAAK;AAAA,IAC1C;AAAA,IAEA,MAAM,WAAW,KAAK,eAAe,IAAI,KAAK;AAAA,IAC9C,SAAS,IAAI,OAAO;AAAA,IAEpB,QAAQ,IAAI,uBAAuB,OAAO;AAAA,IAG1C,OAAO,MAAM;AAAA,MACX,SAAS,OAAO,OAAO;AAAA,MACvB,IAAI,SAAS,SAAS,GAAG;AAAA,QACvB,KAAK,eAAe,OAAO,KAAK;AAAA,MAClC;AAAA;AAAA;AAAA,EAQJ,GAAG,CAAC,OAAe,SAA6B;AAAA,IAC9C,MAAM,WAAW,KAAK,eAAe,IAAI,KAAK;AAAA,IAC9C,IAAI,UAAU;AAAA,MACZ,SAAS,OAAO,OAAO;AAAA,MACvB,IAAI,SAAS,SAAS,GAAG;AAAA,QACvB,KAAK,eAAe,OAAO,KAAK;AAAA,MAClC;AAAA,IACF;AAAA;AAAA,EAOF,UAAU,CAAC,OAAqB;AAAA,IAC9B,KAAK,eAAe,OAAO,KAAK;AAAA;AAAA,EAOlC,cAAc,GAAS;AAAA,IACrB,KAAK,eAAe,MAAM;AAAA;AAAA,EAM5B,KAAK,GAKH;AAAA,IACA,OAAO;AAAA,MACL,SAAS,KAAK,aAAa;AAAA,MAC3B,QAAQ,MAAM,KAAK,KAAK,eAAe,KAAK,CAAC;AAAA,MAC7C,aAAa,KAAK,YAAY,WAAW;AAAA,MACzC,OAAO,KAAK,eAAe;AAAA,IAC7B;AAAA;AAEJ;",
8
+ "debugId": "C15ABCA30BB35BCF64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,130 @@
1
+ import {
2
+ __require,
3
+ __toESM
4
+ } from "../chunk-5va59f7m.js";
5
+
6
+ // src/engine.browser.ts
7
+ var wasmInit = null;
8
+ var WasmEngineClass = null;
9
+ function mapToObject(value) {
10
+ if (value instanceof Map) {
11
+ const obj = {};
12
+ for (const [key, val] of value.entries()) {
13
+ obj[key] = mapToObject(val);
14
+ }
15
+ return obj;
16
+ } else if (Array.isArray(value)) {
17
+ return value.map(mapToObject);
18
+ } else if (value && typeof value === "object" && value.constructor === Object) {
19
+ const obj = {};
20
+ for (const [key, val] of Object.entries(value)) {
21
+ obj[key] = mapToObject(val);
22
+ }
23
+ return obj;
24
+ }
25
+ return value;
26
+ }
27
+
28
+ class Engine {
29
+ wasmEngine = null;
30
+ initialized = false;
31
+ async init(options = {}) {
32
+ if (this.initialized)
33
+ return;
34
+ const wasmPath = options.wasmPath ?? "/hypen_engine_bg.wasm";
35
+ try {
36
+ const wasmModule = await import("../wasm/hypen_engine.js");
37
+ wasmInit = wasmModule.default;
38
+ WasmEngineClass = wasmModule.WasmEngine;
39
+ await wasmInit(wasmPath);
40
+ this.wasmEngine = new WasmEngineClass;
41
+ this.initialized = true;
42
+ } catch (error) {
43
+ console.error("[Hypen] Failed to initialize WASM engine:", error);
44
+ throw error;
45
+ }
46
+ }
47
+ ensureInitialized() {
48
+ if (!this.wasmEngine) {
49
+ throw new Error("Engine not initialized. Call init() first.");
50
+ }
51
+ return this.wasmEngine;
52
+ }
53
+ setRenderCallback(callback) {
54
+ const engine = this.ensureInitialized();
55
+ engine.setRenderCallback((patches) => {
56
+ callback(patches);
57
+ });
58
+ }
59
+ setComponentResolver(resolver) {
60
+ const engine = this.ensureInitialized();
61
+ engine.setComponentResolver((componentName, contextPath) => {
62
+ const result = resolver(componentName, contextPath);
63
+ return result;
64
+ });
65
+ }
66
+ renderSource(source) {
67
+ const engine = this.ensureInitialized();
68
+ engine.renderSource(source);
69
+ }
70
+ renderLazyComponent(source) {
71
+ const engine = this.ensureInitialized();
72
+ engine.renderLazyComponent(source);
73
+ }
74
+ renderInto(source, parentNodeId, state) {
75
+ const engine = this.ensureInitialized();
76
+ const safeState = JSON.parse(JSON.stringify(state));
77
+ engine.renderInto(source, parentNodeId, safeState);
78
+ }
79
+ notifyStateChange(paths, currentState) {
80
+ const engine = this.ensureInitialized();
81
+ const plainObject = JSON.parse(JSON.stringify(currentState));
82
+ engine.updateState(plainObject);
83
+ if (paths.length > 0) {
84
+ console.debug("[Hypen] State changed:", paths);
85
+ }
86
+ }
87
+ updateState(statePatch) {
88
+ const engine = this.ensureInitialized();
89
+ const plainObject = JSON.parse(JSON.stringify(statePatch));
90
+ engine.updateState(plainObject);
91
+ }
92
+ dispatchAction(name, payload) {
93
+ const engine = this.ensureInitialized();
94
+ console.log(`[Engine] Action dispatched: ${name}`);
95
+ engine.dispatchAction(name, payload ?? null);
96
+ }
97
+ onAction(actionName, handler) {
98
+ const engine = this.ensureInitialized();
99
+ engine.onAction(actionName, (action) => {
100
+ const normalizedAction = {
101
+ ...action,
102
+ payload: action.payload ? mapToObject(action.payload) : action.payload
103
+ };
104
+ Promise.resolve(handler(normalizedAction)).catch(console.error);
105
+ });
106
+ }
107
+ setModule(name, actions, stateKeys, initialState) {
108
+ const engine = this.ensureInitialized();
109
+ engine.setModule(name, actions, stateKeys, initialState);
110
+ }
111
+ getRevision() {
112
+ const engine = this.ensureInitialized();
113
+ return engine.getRevision();
114
+ }
115
+ clearTree() {
116
+ const engine = this.ensureInitialized();
117
+ engine.clearTree();
118
+ }
119
+ debugParseComponent(source) {
120
+ const engine = this.ensureInitialized();
121
+ return engine.debugParseComponent(source);
122
+ }
123
+ }
124
+ export {
125
+ Engine
126
+ };
127
+
128
+ export { Engine };
129
+
130
+ //# debugId=FB3794C86EF3E0CF64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/engine.browser.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Browser-compatible wrapper around the WASM engine\n * Uses web target for browser environments\n */\n\n// Dynamic import path - will be configured at build time\n// For browser, the WASM needs to be served and initialized explicitly\nlet wasmInit: ((path?: string) => Promise<void>) | null = null;\nlet WasmEngineClass: any = null;\n\nexport type Patch = {\n type: \"create\" | \"setProp\" | \"setText\" | \"insert\" | \"move\" | \"remove\" | \"attachEvent\" | \"detachEvent\";\n id?: string;\n element_type?: string;\n props?: Record<string, any> | Map<string, any>;\n name?: string;\n value?: any;\n text?: string;\n parent_id?: string;\n before_id?: string;\n event_name?: string;\n};\n\nexport type Action = {\n name: string;\n payload?: any;\n sender?: string;\n};\n\nexport type RenderCallback = (patches: Patch[]) => void;\nexport type ActionHandler = (action: Action) => void | Promise<void>;\n\nexport type ResolvedComponent = {\n source: string;\n path: string;\n};\n\nexport type ComponentResolver = (\n componentName: string,\n contextPath: string | null\n) => ResolvedComponent | null;\n\nexport interface EngineInitOptions {\n /** Path to the WASM file (default: \"/hypen_engine_bg.wasm\") */\n wasmPath?: string;\n}\n\n/**\n * Recursively convert Maps and nested structures to plain objects\n */\nfunction mapToObject(value: any): any {\n if (value instanceof Map) {\n const obj: Record<string, any> = {};\n for (const [key, val] of value.entries()) {\n obj[key] = mapToObject(val);\n }\n return obj;\n } else if (Array.isArray(value)) {\n return value.map(mapToObject);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n const obj: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n obj[key] = mapToObject(val);\n }\n return obj;\n }\n return value;\n}\n\n/**\n * Engine wraps the WASM engine and provides a TypeScript-friendly API\n * Browser version with explicit WASM initialization\n */\nexport class Engine {\n private wasmEngine: any = null;\n private initialized = false;\n\n /**\n * Initialize the WASM module\n * @param options - Initialization options including wasmPath\n */\n async init(options: EngineInitOptions = {}): Promise<void> {\n if (this.initialized) return;\n\n const wasmPath = options.wasmPath ?? \"/hypen_engine_bg.wasm\";\n\n // Dynamically import the WASM module\n // This allows the path to be configured at runtime\n try {\n // @ts-expect-error WASM module is generated at build time\n const wasmModule = await import(\"../wasm/hypen_engine.js\");\n wasmInit = wasmModule.default;\n WasmEngineClass = wasmModule.WasmEngine;\n\n // Initialize WASM with explicit path\n await wasmInit!(wasmPath);\n\n this.wasmEngine = new WasmEngineClass();\n this.initialized = true;\n } catch (error) {\n console.error(\"[Hypen] Failed to initialize WASM engine:\", error);\n throw error;\n }\n }\n\n /**\n * Ensure the engine is initialized before operations\n */\n private ensureInitialized(): any {\n if (!this.wasmEngine) {\n throw new Error(\"Engine not initialized. Call init() first.\");\n }\n return this.wasmEngine;\n }\n\n /**\n * Set the render callback that receives patches\n */\n setRenderCallback(callback: RenderCallback): void {\n const engine = this.ensureInitialized();\n engine.setRenderCallback((patches: Patch[]) => {\n callback(patches);\n });\n }\n\n /**\n * Set the component resolver for dynamic component composition\n */\n setComponentResolver(resolver: ComponentResolver): void {\n const engine = this.ensureInitialized();\n engine.setComponentResolver((componentName: string, contextPath: string | null) => {\n const result = resolver(componentName, contextPath);\n return result;\n });\n }\n\n /**\n * Parse and render Hypen DSL source code\n */\n renderSource(source: string): void {\n const engine = this.ensureInitialized();\n engine.renderSource(source);\n }\n\n /**\n * Render a lazy component (for lazy route loading)\n */\n renderLazyComponent(source: string): void {\n const engine = this.ensureInitialized();\n engine.renderLazyComponent(source);\n }\n\n /**\n * Render a component into a specific parent node (subtree rendering)\n */\n renderInto(source: string, parentNodeId: string, state: Record<string, any>): void {\n const engine = this.ensureInitialized();\n const safeState = JSON.parse(JSON.stringify(state));\n engine.renderInto(source, parentNodeId, safeState);\n }\n\n /**\n * Notify the engine of state changes\n */\n notifyStateChange(paths: string[], currentState: Record<string, any>): void {\n const engine = this.ensureInitialized();\n\n const plainObject = JSON.parse(JSON.stringify(currentState));\n engine.updateState(plainObject);\n\n if (paths.length > 0) {\n console.debug(\"[Hypen] State changed:\", paths);\n }\n }\n\n /**\n * Update state (triggers re-render of affected nodes)\n * @deprecated Use notifyStateChange instead\n */\n updateState(statePatch: Record<string, any>): void {\n const engine = this.ensureInitialized();\n const plainObject = JSON.parse(JSON.stringify(statePatch));\n engine.updateState(plainObject);\n }\n\n /**\n * Dispatch an action\n */\n dispatchAction(name: string, payload?: any): void {\n const engine = this.ensureInitialized();\n console.log(`[Engine] Action dispatched: ${name}`);\n engine.dispatchAction(name, payload ?? null);\n }\n\n /**\n * Register an action handler\n */\n onAction(actionName: string, handler: ActionHandler): void {\n const engine = this.ensureInitialized();\n engine.onAction(actionName, (action: Action) => {\n const normalizedAction: Action = {\n ...action,\n payload: action.payload ? mapToObject(action.payload) : action.payload,\n };\n Promise.resolve(handler(normalizedAction)).catch(console.error);\n });\n }\n\n /**\n * Initialize a module\n */\n setModule(\n name: string,\n actions: string[],\n stateKeys: string[],\n initialState: Record<string, any>\n ): void {\n const engine = this.ensureInitialized();\n engine.setModule(name, actions, stateKeys, initialState);\n }\n\n /**\n * Get the current revision number\n */\n getRevision(): bigint {\n const engine = this.ensureInitialized();\n return engine.getRevision();\n }\n\n /**\n * Clear the engine tree\n */\n clearTree(): void {\n const engine = this.ensureInitialized();\n engine.clearTree();\n }\n\n /**\n * Debug method to inspect parsed components\n */\n debugParseComponent(source: string): string {\n const engine = this.ensureInitialized();\n return engine.debugParseComponent(source);\n }\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "FB3794C86EF3E0CF64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,101 @@
1
+ import"../chunk-5va59f7m.js";
2
+
3
+ // src/engine.ts
4
+ import { WasmEngine } from "../wasm/hypen_engine.js";
5
+
6
+ class Engine {
7
+ wasmEngine = null;
8
+ initialized = false;
9
+ async init() {
10
+ if (this.initialized)
11
+ return;
12
+ this.wasmEngine = new WasmEngine;
13
+ this.initialized = true;
14
+ }
15
+ ensureInitialized() {
16
+ if (!this.wasmEngine) {
17
+ throw new Error("Engine not initialized. Call init() first.");
18
+ }
19
+ return this.wasmEngine;
20
+ }
21
+ setRenderCallback(callback) {
22
+ const engine = this.ensureInitialized();
23
+ engine.setRenderCallback((patches) => {
24
+ callback(patches);
25
+ });
26
+ }
27
+ setComponentResolver(resolver) {
28
+ const engine = this.ensureInitialized();
29
+ engine.setComponentResolver((componentName, contextPath) => {
30
+ const result = resolver(componentName, contextPath);
31
+ return result;
32
+ });
33
+ }
34
+ renderSource(source) {
35
+ const engine = this.ensureInitialized();
36
+ engine.renderSource(source);
37
+ }
38
+ renderLazyComponent(source) {
39
+ const engine = this.ensureInitialized();
40
+ engine.renderLazyComponent(source);
41
+ }
42
+ renderInto(source, parentNodeId, state) {
43
+ const engine = this.ensureInitialized();
44
+ const safeState = JSON.parse(JSON.stringify(state));
45
+ engine.renderInto(source, parentNodeId, safeState);
46
+ }
47
+ notifyStateChange(paths, values) {
48
+ const engine = this.ensureInitialized();
49
+ if (paths.length === 0) {
50
+ return;
51
+ }
52
+ engine.updateStateSparse(paths, values);
53
+ console.debug("[Hypen] State changed (sparse):", paths);
54
+ }
55
+ notifyStateChangeFull(paths, currentState) {
56
+ const engine = this.ensureInitialized();
57
+ const plainObject = JSON.parse(JSON.stringify(currentState));
58
+ engine.updateState(plainObject);
59
+ if (paths.length > 0) {
60
+ console.debug("[Hypen] State changed (full):", paths);
61
+ }
62
+ }
63
+ updateState(statePatch) {
64
+ const engine = this.ensureInitialized();
65
+ const plainObject = JSON.parse(JSON.stringify(statePatch));
66
+ engine.updateState(plainObject);
67
+ }
68
+ dispatchAction(name, payload) {
69
+ const engine = this.ensureInitialized();
70
+ engine.dispatchAction(name, payload ?? null);
71
+ }
72
+ onAction(actionName, handler) {
73
+ const engine = this.ensureInitialized();
74
+ engine.onAction(actionName, (action) => {
75
+ Promise.resolve(handler(action)).catch(console.error);
76
+ });
77
+ }
78
+ setModule(name, actions, stateKeys, initialState) {
79
+ const engine = this.ensureInitialized();
80
+ engine.setModule(name, actions, stateKeys, initialState);
81
+ }
82
+ getRevision() {
83
+ const engine = this.ensureInitialized();
84
+ return engine.getRevision();
85
+ }
86
+ clearTree() {
87
+ const engine = this.ensureInitialized();
88
+ engine.clearTree();
89
+ }
90
+ debugParseComponent(source) {
91
+ const engine = this.ensureInitialized();
92
+ return engine.debugParseComponent(source);
93
+ }
94
+ }
95
+ export {
96
+ Engine
97
+ };
98
+
99
+ export { Engine };
100
+
101
+ //# debugId=289E816B2FB573D464756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/engine.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Low-level wrapper around the WASM engine\n * Node.js / Bundler target\n */\n\n// @ts-expect-error WASM module is generated at build time\nimport { WasmEngine } from \"../wasm/hypen_engine.js\";\n\nexport type Patch = {\n type: \"create\" | \"setProp\" | \"setText\" | \"insert\" | \"move\" | \"remove\" | \"attachEvent\" | \"detachEvent\";\n id?: string;\n elementType?: string;\n props?: Record<string, any>;\n name?: string;\n value?: any;\n text?: string;\n parentId?: string;\n beforeId?: string;\n eventName?: string;\n};\n\nexport type Action = {\n name: string;\n payload?: any;\n sender?: string;\n};\n\nexport type RenderCallback = (patches: Patch[]) => void;\nexport type ActionHandler = (action: Action) => void | Promise<void>;\n\nexport type ResolvedComponent = {\n source: string;\n path: string;\n};\n\nexport type ComponentResolver = (\n componentName: string,\n contextPath: string | null\n) => ResolvedComponent | null;\n\n/**\n * Engine wraps the WASM engine and provides a TypeScript-friendly API\n */\nexport class Engine {\n private wasmEngine: WasmEngine | null = null;\n private initialized = false;\n\n /**\n * Initialize the WASM module\n */\n async init(): Promise<void> {\n if (this.initialized) return;\n\n // For bundler target, WASM is auto-initialized\n this.wasmEngine = new WasmEngine();\n this.initialized = true;\n }\n\n /**\n * Ensure the engine is initialized before operations\n */\n private ensureInitialized(): WasmEngine {\n if (!this.wasmEngine) {\n throw new Error(\"Engine not initialized. Call init() first.\");\n }\n return this.wasmEngine;\n }\n\n /**\n * Set the render callback that receives patches\n */\n setRenderCallback(callback: RenderCallback): void {\n const engine = this.ensureInitialized();\n engine.setRenderCallback((patches: Patch[]) => {\n callback(patches);\n });\n }\n\n /**\n * Set the component resolver for dynamic component composition\n */\n setComponentResolver(resolver: ComponentResolver): void {\n const engine = this.ensureInitialized();\n engine.setComponentResolver((componentName: string, contextPath: string | null) => {\n const result = resolver(componentName, contextPath);\n return result;\n });\n }\n\n /**\n * Parse and render Hypen DSL source code\n */\n renderSource(source: string): void {\n const engine = this.ensureInitialized();\n engine.renderSource(source);\n }\n\n /**\n * Render a lazy component (for lazy route loading)\n */\n renderLazyComponent(source: string): void {\n const engine = this.ensureInitialized();\n engine.renderLazyComponent(source);\n }\n\n /**\n * Render a component into a specific parent node (subtree rendering)\n */\n renderInto(source: string, parentNodeId: string, state: Record<string, any>): void {\n const engine = this.ensureInitialized();\n const safeState = JSON.parse(JSON.stringify(state));\n engine.renderInto(source, parentNodeId, safeState);\n }\n\n /**\n * Notify the engine of state changes using sparse updates\n */\n notifyStateChange(paths: string[], values: Record<string, any>): void {\n const engine = this.ensureInitialized();\n\n if (paths.length === 0) {\n return;\n }\n\n engine.updateStateSparse(paths, values);\n console.debug(\"[Hypen] State changed (sparse):\", paths);\n }\n\n /**\n * Notify the engine of state changes using full state replacement\n * @deprecated Use notifyStateChange with sparse values instead\n */\n notifyStateChangeFull(paths: string[], currentState: Record<string, any>): void {\n const engine = this.ensureInitialized();\n\n const plainObject = JSON.parse(JSON.stringify(currentState));\n engine.updateState(plainObject);\n\n if (paths.length > 0) {\n console.debug(\"[Hypen] State changed (full):\", paths);\n }\n }\n\n /**\n * Update state (triggers re-render of affected nodes)\n * @deprecated Use notifyStateChange instead\n */\n updateState(statePatch: Record<string, any>): void {\n const engine = this.ensureInitialized();\n const plainObject = JSON.parse(JSON.stringify(statePatch));\n engine.updateState(plainObject);\n }\n\n /**\n * Dispatch an action\n */\n dispatchAction(name: string, payload?: any): void {\n const engine = this.ensureInitialized();\n engine.dispatchAction(name, payload ?? null);\n }\n\n /**\n * Register an action handler\n */\n onAction(actionName: string, handler: ActionHandler): void {\n const engine = this.ensureInitialized();\n engine.onAction(actionName, (action: Action) => {\n Promise.resolve(handler(action)).catch(console.error);\n });\n }\n\n /**\n * Initialize a module\n */\n setModule(\n name: string,\n actions: string[],\n stateKeys: string[],\n initialState: Record<string, any>\n ): void {\n const engine = this.ensureInitialized();\n engine.setModule(name, actions, stateKeys, initialState);\n }\n\n /**\n * Get the current revision number\n */\n getRevision(): number {\n const engine = this.ensureInitialized();\n return engine.getRevision();\n }\n\n /**\n * Clear the engine tree\n */\n clearTree(): void {\n const engine = this.ensureInitialized();\n engine.clearTree();\n }\n\n /**\n * Debug method to inspect parsed components\n */\n debugParseComponent(source: string): string {\n const engine = this.ensureInitialized();\n return engine.debugParseComponent(source);\n }\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "289E816B2FB573D464756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,72 @@
1
+ import"../chunk-5va59f7m.js";
2
+
3
+ // src/events.ts
4
+ class TypedEventEmitter {
5
+ eventBus = new Map;
6
+ emit(event, payload) {
7
+ const handlers = this.eventBus.get(event);
8
+ if (!handlers || handlers.size === 0) {
9
+ return;
10
+ }
11
+ handlers.forEach((handler) => {
12
+ try {
13
+ handler(payload);
14
+ } catch (error) {
15
+ console.error(`Error in event handler for "${String(event)}":`, error);
16
+ }
17
+ });
18
+ }
19
+ on(event, handler) {
20
+ if (!this.eventBus.has(event)) {
21
+ this.eventBus.set(event, new Set);
22
+ }
23
+ const handlers = this.eventBus.get(event);
24
+ handlers.add(handler);
25
+ return () => {
26
+ handlers.delete(handler);
27
+ if (handlers.size === 0) {
28
+ this.eventBus.delete(event);
29
+ }
30
+ };
31
+ }
32
+ once(event, handler) {
33
+ const wrappedHandler = (payload) => {
34
+ handler(payload);
35
+ unsubscribe();
36
+ };
37
+ const unsubscribe = this.on(event, wrappedHandler);
38
+ return unsubscribe;
39
+ }
40
+ off(event, handler) {
41
+ const handlers = this.eventBus.get(event);
42
+ if (handlers) {
43
+ handlers.delete(handler);
44
+ if (handlers.size === 0) {
45
+ this.eventBus.delete(event);
46
+ }
47
+ }
48
+ }
49
+ removeAllListeners(event) {
50
+ this.eventBus.delete(event);
51
+ }
52
+ clearAll() {
53
+ this.eventBus.clear();
54
+ }
55
+ listenerCount(event) {
56
+ return this.eventBus.get(event)?.size ?? 0;
57
+ }
58
+ eventNames() {
59
+ return Array.from(this.eventBus.keys());
60
+ }
61
+ }
62
+ function createEventEmitter() {
63
+ return new TypedEventEmitter;
64
+ }
65
+ export {
66
+ createEventEmitter,
67
+ TypedEventEmitter
68
+ };
69
+
70
+ export { TypedEventEmitter, createEventEmitter };
71
+
72
+ //# debugId=3E73DEFF207B663B64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/events.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Type-safe Event System\n *\n * Provides strongly-typed event emission and subscription with autocomplete support.\n */\n\nexport type EventHandler<T = unknown> = (payload: T) => void;\n\n/**\n * Type-safe event emitter with generics\n */\nexport class TypedEventEmitter<TEvents extends Record<string, unknown> = Record<string, unknown>> {\n private eventBus = new Map<keyof TEvents, Set<EventHandler<any>>>();\n\n /**\n * Emit an event with type-safe payload\n */\n emit<K extends keyof TEvents>(event: K, payload: TEvents[K]): void {\n const handlers = this.eventBus.get(event);\n if (!handlers || handlers.size === 0) {\n return;\n }\n\n handlers.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n console.error(`Error in event handler for \"${String(event)}\":`, error);\n }\n });\n }\n\n /**\n * Subscribe to an event with type-safe payload\n * Returns an unsubscribe function\n */\n on<K extends keyof TEvents>(event: K, handler: EventHandler<TEvents[K]>): () => void {\n if (!this.eventBus.has(event)) {\n this.eventBus.set(event, new Set());\n }\n\n const handlers = this.eventBus.get(event)!;\n handlers.add(handler);\n\n // Return unsubscribe function\n return () => {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this.eventBus.delete(event);\n }\n };\n }\n\n /**\n * Subscribe to an event once (auto-unsubscribe after first emit)\n */\n once<K extends keyof TEvents>(event: K, handler: EventHandler<TEvents[K]>): () => void {\n const wrappedHandler = (payload: TEvents[K]) => {\n handler(payload);\n unsubscribe();\n };\n\n const unsubscribe = this.on(event, wrappedHandler);\n return unsubscribe;\n }\n\n /**\n * Unsubscribe a specific handler from an event\n */\n off<K extends keyof TEvents>(event: K, handler: EventHandler<TEvents[K]>): void {\n const handlers = this.eventBus.get(event);\n if (handlers) {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this.eventBus.delete(event);\n }\n }\n }\n\n /**\n * Remove all listeners for a specific event\n */\n removeAllListeners<K extends keyof TEvents>(event: K): void {\n this.eventBus.delete(event);\n }\n\n /**\n * Remove all listeners for all events\n */\n clearAll(): void {\n this.eventBus.clear();\n }\n\n /**\n * Get the number of listeners for an event\n */\n listenerCount<K extends keyof TEvents>(event: K): number {\n return this.eventBus.get(event)?.size ?? 0;\n }\n\n /**\n * Get all registered event names\n */\n eventNames(): Array<keyof TEvents> {\n return Array.from(this.eventBus.keys());\n }\n}\n\n/**\n * Default events for Hypen framework (can be extended by users)\n */\nexport type HypenFrameworkEvents = {\n 'module:created': { moduleId: string };\n 'module:destroyed': { moduleId: string };\n 'route:changed': { from: string | null; to: string };\n 'state:updated': { moduleId: string; paths: string[] };\n 'action:dispatched': { moduleId: string; actionName: string; payload?: unknown };\n 'error': { message: string; error?: Error; context?: string };\n};\n\n/**\n * Create a typed event emitter with custom event map\n */\nexport function createEventEmitter<TEvents extends Record<string, unknown> = HypenFrameworkEvents>(): TypedEventEmitter<TEvents> {\n return new TypedEventEmitter<TEvents>();\n}\n"
6
+ ],
7
+ "mappings": ";;;AAWO,MAAM,kBAAqF;AAAA,EACxF,WAAW,IAAI;AAAA,EAKvB,IAA6B,CAAC,OAAU,SAA2B;AAAA,IACjE,MAAM,WAAW,KAAK,SAAS,IAAI,KAAK;AAAA,IACxC,IAAI,CAAC,YAAY,SAAS,SAAS,GAAG;AAAA,MACpC;AAAA,IACF;AAAA,IAEA,SAAS,QAAQ,CAAC,YAAY;AAAA,MAC5B,IAAI;AAAA,QACF,QAAQ,OAAO;AAAA,QACf,OAAO,OAAO;AAAA,QACd,QAAQ,MAAM,+BAA+B,OAAO,KAAK,OAAO,KAAK;AAAA;AAAA,KAExE;AAAA;AAAA,EAOH,EAA2B,CAAC,OAAU,SAA+C;AAAA,IACnF,IAAI,CAAC,KAAK,SAAS,IAAI,KAAK,GAAG;AAAA,MAC7B,KAAK,SAAS,IAAI,OAAO,IAAI,GAAK;AAAA,IACpC;AAAA,IAEA,MAAM,WAAW,KAAK,SAAS,IAAI,KAAK;AAAA,IACxC,SAAS,IAAI,OAAO;AAAA,IAGpB,OAAO,MAAM;AAAA,MACX,SAAS,OAAO,OAAO;AAAA,MACvB,IAAI,SAAS,SAAS,GAAG;AAAA,QACvB,KAAK,SAAS,OAAO,KAAK;AAAA,MAC5B;AAAA;AAAA;AAAA,EAOJ,IAA6B,CAAC,OAAU,SAA+C;AAAA,IACrF,MAAM,iBAAiB,CAAC,YAAwB;AAAA,MAC9C,QAAQ,OAAO;AAAA,MACf,YAAY;AAAA;AAAA,IAGd,MAAM,cAAc,KAAK,GAAG,OAAO,cAAc;AAAA,IACjD,OAAO;AAAA;AAAA,EAMT,GAA4B,CAAC,OAAU,SAAyC;AAAA,IAC9E,MAAM,WAAW,KAAK,SAAS,IAAI,KAAK;AAAA,IACxC,IAAI,UAAU;AAAA,MACZ,SAAS,OAAO,OAAO;AAAA,MACvB,IAAI,SAAS,SAAS,GAAG;AAAA,QACvB,KAAK,SAAS,OAAO,KAAK;AAAA,MAC5B;AAAA,IACF;AAAA;AAAA,EAMF,kBAA2C,CAAC,OAAgB;AAAA,IAC1D,KAAK,SAAS,OAAO,KAAK;AAAA;AAAA,EAM5B,QAAQ,GAAS;AAAA,IACf,KAAK,SAAS,MAAM;AAAA;AAAA,EAMtB,aAAsC,CAAC,OAAkB;AAAA,IACvD,OAAO,KAAK,SAAS,IAAI,KAAK,GAAG,QAAQ;AAAA;AAAA,EAM3C,UAAU,GAAyB;AAAA,IACjC,OAAO,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC;AAAA;AAE1C;AAiBO,SAAS,kBAAkF,GAA+B;AAAA,EAC/H,OAAO,IAAI;AAAA;",
8
+ "debugId": "3E73DEFF207B663B64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,51 @@
1
+ import {
2
+ HypenGlobalContext
3
+ } from "./context.js";
4
+ import {
5
+ TypedEventEmitter,
6
+ createEventEmitter
7
+ } from "./events.js";
8
+ import {
9
+ RemoteEngine
10
+ } from "./remote/client.js";
11
+ import {
12
+ Engine
13
+ } from "./engine.browser.js";
14
+ import {
15
+ HypenApp,
16
+ HypenAppBuilder,
17
+ HypenModuleInstance,
18
+ app
19
+ } from "./app.js";
20
+ import {
21
+ BaseRenderer,
22
+ ConsoleRenderer
23
+ } from "./renderer.js";
24
+ import {
25
+ HypenRouter
26
+ } from "./router.js";
27
+ import {
28
+ batchStateUpdates,
29
+ createObservableState,
30
+ getStateSnapshot
31
+ } from "./state.js";
32
+ import"../chunk-5va59f7m.js";
33
+ export {
34
+ getStateSnapshot,
35
+ createObservableState,
36
+ createEventEmitter,
37
+ batchStateUpdates,
38
+ app,
39
+ TypedEventEmitter,
40
+ RemoteEngine,
41
+ HypenRouter,
42
+ HypenModuleInstance,
43
+ HypenGlobalContext,
44
+ HypenAppBuilder,
45
+ HypenApp,
46
+ Engine,
47
+ ConsoleRenderer,
48
+ BaseRenderer
49
+ };
50
+
51
+ //# debugId=46A5B55EE5F02FAE64756E2164756E21
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "46A5B55EE5F02FAE64756E2164756E21",
8
+ "names": []
9
+ }
@@ -0,0 +1,55 @@
1
+ import {
2
+ HypenGlobalContext
3
+ } from "./context.js";
4
+ import {
5
+ TypedEventEmitter,
6
+ createEventEmitter
7
+ } from "./events.js";
8
+ import {
9
+ RemoteEngine
10
+ } from "./remote/client.js";
11
+ import {
12
+ Engine
13
+ } from "./engine.js";
14
+ import {
15
+ Engine as Engine2
16
+ } from "./engine.browser.js";
17
+ import {
18
+ HypenApp,
19
+ HypenAppBuilder,
20
+ HypenModuleInstance,
21
+ app
22
+ } from "./app.js";
23
+ import {
24
+ BaseRenderer,
25
+ ConsoleRenderer
26
+ } from "./renderer.js";
27
+ import {
28
+ HypenRouter
29
+ } from "./router.js";
30
+ import {
31
+ batchStateUpdates,
32
+ createObservableState,
33
+ getStateSnapshot
34
+ } from "./state.js";
35
+ import"../chunk-5va59f7m.js";
36
+ export {
37
+ getStateSnapshot,
38
+ createObservableState,
39
+ createEventEmitter,
40
+ batchStateUpdates,
41
+ app,
42
+ TypedEventEmitter,
43
+ RemoteEngine,
44
+ HypenRouter,
45
+ HypenModuleInstance,
46
+ HypenGlobalContext,
47
+ HypenAppBuilder,
48
+ HypenApp,
49
+ Engine,
50
+ ConsoleRenderer,
51
+ Engine2 as BrowserEngine,
52
+ BaseRenderer
53
+ };
54
+
55
+ //# debugId=EB143B4A76F9CB1464756E2164756E21
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "EB143B4A76F9CB1464756E2164756E21",
8
+ "names": []
9
+ }