@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,22 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ export { __toESM, __require };
21
+
22
+ //# debugId=139229FD8440C0D464756E2164756E21
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "139229FD8440C0D464756E2164756E21",
8
+ "names": []
9
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Low-level wrapper around the WASM engine
3
+ * Node.js / Bundler target
4
+ */
5
+ export declare type Patch = {
6
+ type: "create" | "setProp" | "setText" | "insert" | "move" | "remove" | "attachEvent" | "detachEvent";
7
+ id?: string;
8
+ elementType?: string;
9
+ props?: Record<string, any>;
10
+ name?: string;
11
+ value?: any;
12
+ text?: string;
13
+ parentId?: string;
14
+ beforeId?: string;
15
+ eventName?: string;
16
+ };
17
+ export declare type Action = {
18
+ name: string;
19
+ payload?: any;
20
+ sender?: string;
21
+ };
22
+ export declare type RenderCallback = (patches: Patch[]) => void;
23
+ export declare type ActionHandler = (action: Action) => void | Promise<void>;
24
+ export declare type ResolvedComponent = {
25
+ source: string;
26
+ path: string;
27
+ };
28
+ export declare type ComponentResolver = (componentName: string, contextPath: string | null) => ResolvedComponent | null;
29
+ /**
30
+ * Engine wraps the WASM engine and provides a TypeScript-friendly API
31
+ */
32
+ export declare class Engine {
33
+ private wasmEngine;
34
+ private initialized;
35
+ /**
36
+ * Initialize the WASM module
37
+ */
38
+ init(): Promise<void>;
39
+ /**
40
+ * Ensure the engine is initialized before operations
41
+ */
42
+ private ensureInitialized;
43
+ /**
44
+ * Set the render callback that receives patches
45
+ */
46
+ setRenderCallback(callback: RenderCallback): void;
47
+ /**
48
+ * Set the component resolver for dynamic component composition
49
+ */
50
+ setComponentResolver(resolver: ComponentResolver): void;
51
+ /**
52
+ * Parse and render Hypen DSL source code
53
+ */
54
+ renderSource(source: string): void;
55
+ /**
56
+ * Render a lazy component (for lazy route loading)
57
+ */
58
+ renderLazyComponent(source: string): void;
59
+ /**
60
+ * Render a component into a specific parent node (subtree rendering)
61
+ */
62
+ renderInto(source: string, parentNodeId: string, state: Record<string, any>): void;
63
+ /**
64
+ * Notify the engine of state changes using sparse updates
65
+ */
66
+ notifyStateChange(paths: string[], values: Record<string, any>): void;
67
+ /**
68
+ * Notify the engine of state changes using full state replacement
69
+ * @deprecated Use notifyStateChange with sparse values instead
70
+ */
71
+ notifyStateChangeFull(paths: string[], currentState: Record<string, any>): void;
72
+ /**
73
+ * Update state (triggers re-render of affected nodes)
74
+ * @deprecated Use notifyStateChange instead
75
+ */
76
+ updateState(statePatch: Record<string, any>): void;
77
+ /**
78
+ * Dispatch an action
79
+ */
80
+ dispatchAction(name: string, payload?: any): void;
81
+ /**
82
+ * Register an action handler
83
+ */
84
+ onAction(actionName: string, handler: ActionHandler): void;
85
+ /**
86
+ * Initialize a module
87
+ */
88
+ setModule(name: string, actions: string[], stateKeys: string[], initialState: Record<string, any>): void;
89
+ /**
90
+ * Get the current revision number
91
+ */
92
+ getRevision(): number;
93
+ /**
94
+ * Clear the engine tree
95
+ */
96
+ clearTree(): void;
97
+ /**
98
+ * Debug method to inspect parsed components
99
+ */
100
+ debugParseComponent(source: string): string;
101
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Type-safe Event System
3
+ *
4
+ * Provides strongly-typed event emission and subscription with autocomplete support.
5
+ */
6
+ export declare type EventHandler<T = unknown> = (payload: T) => void;
7
+ /**
8
+ * Type-safe event emitter with generics
9
+ */
10
+ export declare class TypedEventEmitter<TEvents extends Record<string, unknown> = Record<string, unknown>> {
11
+ private eventBus;
12
+ /**
13
+ * Emit an event with type-safe payload
14
+ */
15
+ emit<K extends keyof TEvents>(event: K, payload: TEvents[K]): void;
16
+ /**
17
+ * Subscribe to an event with type-safe payload
18
+ * Returns an unsubscribe function
19
+ */
20
+ on<K extends keyof TEvents>(event: K, handler: EventHandler<TEvents[K]>): () => void;
21
+ /**
22
+ * Subscribe to an event once (auto-unsubscribe after first emit)
23
+ */
24
+ once<K extends keyof TEvents>(event: K, handler: EventHandler<TEvents[K]>): () => void;
25
+ /**
26
+ * Unsubscribe a specific handler from an event
27
+ */
28
+ off<K extends keyof TEvents>(event: K, handler: EventHandler<TEvents[K]>): void;
29
+ /**
30
+ * Remove all listeners for a specific event
31
+ */
32
+ removeAllListeners<K extends keyof TEvents>(event: K): void;
33
+ /**
34
+ * Remove all listeners for all events
35
+ */
36
+ clearAll(): void;
37
+ /**
38
+ * Get the number of listeners for an event
39
+ */
40
+ listenerCount<K extends keyof TEvents>(event: K): number;
41
+ /**
42
+ * Get all registered event names
43
+ */
44
+ eventNames(): Array<keyof TEvents>;
45
+ }
46
+ /**
47
+ * Default events for Hypen framework (can be extended by users)
48
+ */
49
+ export declare type HypenFrameworkEvents = {
50
+ 'module:created': {
51
+ moduleId: string;
52
+ };
53
+ 'module:destroyed': {
54
+ moduleId: string;
55
+ };
56
+ 'route:changed': {
57
+ from: string | null;
58
+ to: string;
59
+ };
60
+ 'state:updated': {
61
+ moduleId: string;
62
+ paths: string[];
63
+ };
64
+ 'action:dispatched': {
65
+ moduleId: string;
66
+ actionName: string;
67
+ payload?: unknown;
68
+ };
69
+ 'error': {
70
+ message: string;
71
+ error?: Error;
72
+ context?: string;
73
+ };
74
+ };
75
+ /**
76
+ * Create a typed event emitter with custom event map
77
+ */
78
+ export declare function createEventEmitter<TEvents extends Record<string, unknown> = HypenFrameworkEvents>(): TypedEventEmitter<TEvents>;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @hypen/core - Browser Entry Point
3
+ *
4
+ * This entry point uses the browser-compatible engine with explicit WASM initialization.
5
+ */
6
+ export { Engine } from "./engine.browser.js";
7
+ export { app, HypenApp, HypenAppBuilder, HypenModuleInstance } from "./app.js";
8
+ export { createObservableState, batchStateUpdates, getStateSnapshot, } from "./state.js";
9
+ export { BaseRenderer, ConsoleRenderer } from "./renderer.js";
10
+ export { HypenRouter } from "./router.js";
11
+ export { TypedEventEmitter, createEventEmitter } from "./events.js";
12
+ export { HypenGlobalContext } from "./context.js";
13
+ export { RemoteEngine } from "./remote/client.js";
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @hypen/core - Hypen Core Engine
3
+ *
4
+ * Platform-agnostic reactive UI runtime.
5
+ * Use with @hypen/web for browser rendering, or build your own renderer.
6
+ *
7
+ * ## Quick Start
8
+ *
9
+ * ```typescript
10
+ * import { Engine, app } from "@hypen/core";
11
+ *
12
+ * // Create a stateful module
13
+ * const counter = app
14
+ * .defineState({ count: 0 })
15
+ * .onAction("increment", ({ state }) => {
16
+ * state.count++;
17
+ * })
18
+ * .build();
19
+ *
20
+ * // Initialize the engine
21
+ * const engine = new Engine();
22
+ * await engine.init();
23
+ * ```
24
+ */
25
+ export { Engine } from "./engine.js";
26
+ export { Engine as BrowserEngine } from "./engine.browser.js";
27
+ export { app, HypenApp, HypenAppBuilder, HypenModuleInstance } from "./app.js";
28
+ export { createObservableState, batchStateUpdates, getStateSnapshot, } from "./state.js";
29
+ export { BaseRenderer, ConsoleRenderer } from "./renderer.js";
30
+ export { HypenRouter } from "./router.js";
31
+ export { TypedEventEmitter, createEventEmitter } from "./events.js";
32
+ export { HypenGlobalContext } from "./context.js";
33
+ export { RemoteEngine } from "./remote/client.js";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Remote UI streaming for Hypen
3
+ *
4
+ * Client-side: Connect to remote Hypen apps
5
+ */
6
+ export { RemoteEngine } from "./client.js";
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Hypen Router - Declarative routing system
3
+ * Integrated with Hypen's reactive state management
4
+ */
5
+ export declare type RouteMatch = {
6
+ params: Record<string, string>;
7
+ query: Record<string, string>;
8
+ path: string;
9
+ };
10
+ export declare type RouteState = {
11
+ currentPath: string;
12
+ params: Record<string, string>;
13
+ query: Record<string, string>;
14
+ previousPath: string | null;
15
+ };
16
+ export declare type RouteChangeCallback = (route: RouteState) => void;
17
+ /**
18
+ * Hypen Router - Manages application routing with pattern matching
19
+ */
20
+ export declare class HypenRouter {
21
+ private state;
22
+ private subscribers;
23
+ private isInitialized;
24
+ constructor();
25
+ /**
26
+ * Initialize browser history sync
27
+ */
28
+ private initializeBrowserSync;
29
+ /**
30
+ * Get path from browser URL (supports both hash and pathname)
31
+ */
32
+ private getPathFromBrowser;
33
+ /**
34
+ * Parse query string from URL
35
+ */
36
+ private parseQuery;
37
+ /**
38
+ * Navigate to a new path
39
+ */
40
+ push(path: string): void;
41
+ /**
42
+ * Replace current path without adding to history
43
+ */
44
+ replace(path: string): void;
45
+ /**
46
+ * Go back in history
47
+ */
48
+ back(): void;
49
+ /**
50
+ * Go forward in history
51
+ */
52
+ forward(): void;
53
+ /**
54
+ * Update the current path
55
+ */
56
+ private updatePath;
57
+ /**
58
+ * Get current path
59
+ */
60
+ getCurrentPath(): string;
61
+ /**
62
+ * Get current route params
63
+ */
64
+ getParams(): Record<string, string>;
65
+ /**
66
+ * Get current query params
67
+ */
68
+ getQuery(): Record<string, string>;
69
+ /**
70
+ * Get full route state snapshot
71
+ */
72
+ getState(): RouteState;
73
+ /**
74
+ * Match a pattern against a path
75
+ */
76
+ matchPath(pattern: string, path: string): RouteMatch | null;
77
+ /**
78
+ * Subscribe to route changes
79
+ */
80
+ onNavigate(callback: RouteChangeCallback): () => void;
81
+ /**
82
+ * Notify all subscribers of route change
83
+ */
84
+ private notifySubscribers;
85
+ /**
86
+ * Check if a path matches the current route
87
+ */
88
+ isActive(pattern: string): boolean;
89
+ /**
90
+ * Get a URL with query params
91
+ */
92
+ buildUrl(path: string, query?: Record<string, string>): string;
93
+ }
@@ -0,0 +1,160 @@
1
+ import {
2
+ createObservableState,
3
+ getStateSnapshot
4
+ } from "./state.js";
5
+ import"../chunk-5va59f7m.js";
6
+
7
+ // src/app.ts
8
+ class HypenAppBuilder {
9
+ initialState;
10
+ options;
11
+ createdHandler;
12
+ actionHandlers = new Map;
13
+ destroyedHandler;
14
+ constructor(initialState, options) {
15
+ this.initialState = initialState;
16
+ this.options = options || {};
17
+ }
18
+ onCreated(fn) {
19
+ this.createdHandler = fn;
20
+ return this;
21
+ }
22
+ onAction(name, fn) {
23
+ this.actionHandlers.set(name, fn);
24
+ return this;
25
+ }
26
+ onDestroyed(fn) {
27
+ this.destroyedHandler = fn;
28
+ return this;
29
+ }
30
+ build() {
31
+ const stateKeys = this.initialState !== null && typeof this.initialState === "object" ? Object.keys(this.initialState) : [];
32
+ return {
33
+ name: this.options.name,
34
+ actions: Array.from(this.actionHandlers.keys()),
35
+ stateKeys,
36
+ persist: this.options.persist,
37
+ version: this.options.version,
38
+ initialState: this.initialState,
39
+ handlers: {
40
+ onCreated: this.createdHandler,
41
+ onAction: this.actionHandlers,
42
+ onDestroyed: this.destroyedHandler
43
+ }
44
+ };
45
+ }
46
+ }
47
+
48
+ class HypenApp {
49
+ defineState(initial, options) {
50
+ return new HypenAppBuilder(initial, options);
51
+ }
52
+ }
53
+ var app = new HypenApp;
54
+
55
+ class HypenModuleInstance {
56
+ engine;
57
+ definition;
58
+ state;
59
+ isDestroyed = false;
60
+ routerContext;
61
+ globalContext;
62
+ stateChangeCallbacks = [];
63
+ constructor(engine, definition, routerContext, globalContext) {
64
+ this.engine = engine;
65
+ this.definition = definition;
66
+ this.routerContext = routerContext;
67
+ this.globalContext = globalContext;
68
+ this.state = createObservableState(definition.initialState, {
69
+ onChange: (change) => {
70
+ this.engine.notifyStateChange(change.paths, change.newValues);
71
+ this.stateChangeCallbacks.forEach((cb) => cb());
72
+ }
73
+ });
74
+ this.engine.setModule(definition.name || "AnonymousModule", definition.actions, definition.stateKeys, getStateSnapshot(this.state));
75
+ for (const [actionName, handler] of definition.handlers.onAction) {
76
+ console.log(`[ModuleInstance] Registering action handler: ${actionName} for module ${definition.name}`);
77
+ this.engine.onAction(actionName, async (action) => {
78
+ console.log(`[ModuleInstance] Action handler fired: ${actionName}`, action);
79
+ const actionCtx = {
80
+ name: action.name,
81
+ payload: action.payload,
82
+ sender: action.sender
83
+ };
84
+ const next = {
85
+ router: this.routerContext?.root || null
86
+ };
87
+ const context = this.globalContext ? this.createGlobalContextAPI() : undefined;
88
+ try {
89
+ await handler({
90
+ action: actionCtx,
91
+ state: this.state,
92
+ next,
93
+ context
94
+ });
95
+ console.log(`[ModuleInstance] Action handler completed: ${actionName}`);
96
+ } catch (error) {
97
+ console.error(`[ModuleInstance] Action handler error for ${actionName}:`, error);
98
+ }
99
+ });
100
+ }
101
+ this.callCreatedHandler();
102
+ }
103
+ createGlobalContextAPI() {
104
+ if (!this.globalContext) {
105
+ throw new Error("Global context not available");
106
+ }
107
+ const ctx = this.globalContext;
108
+ const api = {
109
+ getModule: (id) => ctx.getModule(id),
110
+ hasModule: (id) => ctx.hasModule(id),
111
+ getModuleIds: () => ctx.getModuleIds(),
112
+ getGlobalState: () => ctx.getGlobalState(),
113
+ emit: (event, payload) => ctx.emit(event, payload),
114
+ on: (event, handler) => ctx.on(event, handler)
115
+ };
116
+ if (ctx.__router) {
117
+ api.__router = ctx.__router;
118
+ }
119
+ if (ctx.__hypenEngine) {
120
+ api.__hypenEngine = ctx.__hypenEngine;
121
+ }
122
+ return api;
123
+ }
124
+ async callCreatedHandler() {
125
+ if (this.definition.handlers.onCreated) {
126
+ const context = this.globalContext ? this.createGlobalContextAPI() : undefined;
127
+ await this.definition.handlers.onCreated(this.state, context);
128
+ }
129
+ }
130
+ onStateChange(callback) {
131
+ this.stateChangeCallbacks.push(callback);
132
+ }
133
+ async destroy() {
134
+ if (this.isDestroyed)
135
+ return;
136
+ if (this.definition.handlers.onDestroyed) {
137
+ await this.definition.handlers.onDestroyed(this.state);
138
+ }
139
+ this.isDestroyed = true;
140
+ }
141
+ getState() {
142
+ return getStateSnapshot(this.state);
143
+ }
144
+ getLiveState() {
145
+ return this.state;
146
+ }
147
+ updateState(patch) {
148
+ Object.assign(this.state, patch);
149
+ }
150
+ }
151
+ export {
152
+ app,
153
+ HypenModuleInstance,
154
+ HypenAppBuilder,
155
+ HypenApp
156
+ };
157
+
158
+ export { HypenAppBuilder, HypenApp, app, HypenModuleInstance };
159
+
160
+ //# debugId=220ACA4FDA4DC86164756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/app.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Hypen App Builder API\n * Implements the stateful module system from RFC-0001\n */\n\nimport type { Action } from \"./engine.js\";\n\n// Interface for engine compatibility (works with both engine.js and engine.browser.js)\nexport interface IEngine {\n setModule(name: string, actions: string[], stateKeys: string[], initialState: unknown): void;\n onAction(actionName: string, handler: (action: Action) => void | Promise<void>): void;\n notifyStateChange(paths: string[], changedValues: Record<string, unknown>): void;\n}\n\nimport { createObservableState, type StateChange, getStateSnapshot } from \"./state.js\";\nimport type { HypenRouter } from \"./router.js\";\nimport type { HypenGlobalContext, ModuleReference } from \"./context.js\";\n\nexport type RouterContext = {\n root: HypenRouter;\n current?: HypenRouter;\n parent?: HypenRouter;\n};\n\nexport type ActionContext = {\n name: string;\n payload?: unknown;\n sender?: string;\n};\n\nexport type ActionNext = {\n router: HypenRouter; // Direct access to router instance (from nearest parent)\n};\n\nexport type GlobalContext = {\n getModule: <T = unknown>(id: string) => ModuleReference<T>;\n hasModule: (id: string) => boolean;\n getModuleIds: () => string[];\n getGlobalState: () => Record<string, unknown>;\n emit: (event: string, payload?: unknown) => void;\n on: (event: string, handler: (payload?: unknown) => void) => () => void;\n __router?: unknown; // Internal: router instance for built-in Router component\n};\n\nexport type LifecycleHandler<T> = (\n state: T,\n context?: GlobalContext\n) => void | Promise<void>;\n\n/**\n * Action handler context - all parameters available explicitly\n */\nexport interface ActionHandlerContext<T> {\n action: ActionContext;\n state: T;\n next: ActionNext;\n context: GlobalContext;\n}\n\n/**\n * Action handler - receives all context in a single object\n */\nexport type ActionHandler<T> = (ctx: ActionHandlerContext<T>) => void | Promise<void>;\n\nexport interface HypenModuleDefinition<T = unknown> {\n name?: string;\n actions: string[];\n stateKeys: string[];\n persist?: boolean;\n version?: number;\n initialState: T;\n handlers: {\n onCreated?: LifecycleHandler<T>;\n onAction: Map<string, ActionHandler<T>>;\n onDestroyed?: LifecycleHandler<T>;\n };\n}\n\n/**\n * Alias for HypenModuleDefinition for backward compatibility\n */\nexport type HypenModule<T = unknown> = HypenModuleDefinition<T>;\n\n/**\n * Builder for creating Hypen app modules\n */\nexport class HypenAppBuilder<T> {\n private initialState: T;\n private options: { persist?: boolean; version?: number; name?: string };\n private createdHandler?: LifecycleHandler<T>;\n private actionHandlers: Map<string, ActionHandler<T>> = new Map();\n private destroyedHandler?: LifecycleHandler<T>;\n\n constructor(\n initialState: T,\n options?: { persist?: boolean; version?: number; name?: string }\n ) {\n this.initialState = initialState;\n this.options = options || {};\n }\n\n /**\n * Register a handler for module creation\n */\n onCreated(fn: LifecycleHandler<T>): this {\n this.createdHandler = fn;\n return this;\n }\n\n /**\n * Register a handler for a specific action\n */\n onAction(name: string, fn: ActionHandler<T>): this {\n this.actionHandlers.set(name, fn);\n return this;\n }\n\n /**\n * Register a handler for module destruction\n */\n onDestroyed(fn: LifecycleHandler<T>): this {\n this.destroyedHandler = fn;\n return this;\n }\n\n /**\n * Build the module definition\n */\n build(): HypenModuleDefinition<T> {\n // Safe way to get keys from initialState\n const stateKeys = this.initialState !== null && typeof this.initialState === 'object'\n ? Object.keys(this.initialState)\n : [];\n\n return {\n name: this.options.name,\n actions: Array.from(this.actionHandlers.keys()),\n stateKeys,\n persist: this.options.persist,\n version: this.options.version,\n initialState: this.initialState,\n handlers: {\n onCreated: this.createdHandler,\n onAction: this.actionHandlers,\n onDestroyed: this.destroyedHandler,\n },\n };\n }\n}\n\n/**\n * Hypen App API\n */\nexport class HypenApp {\n /**\n * Define the initial state for a module\n */\n defineState<T>(\n initial: T,\n options?: { persist?: boolean; version?: number; name?: string }\n ): HypenAppBuilder<T> {\n return new HypenAppBuilder(initial, options);\n }\n}\n\n/**\n * The main app instance for creating modules\n */\nexport const app = new HypenApp();\n\n/**\n * Module Instance - manages a running module with typed state\n */\nexport class HypenModuleInstance<T extends object = any> {\n private engine: IEngine;\n private definition: HypenModuleDefinition<T>;\n private state: T;\n private isDestroyed = false;\n private routerContext?: RouterContext;\n private globalContext?: HypenGlobalContext;\n private stateChangeCallbacks: Array<() => void> = [];\n\n constructor(\n engine: IEngine,\n definition: HypenModuleDefinition<T>,\n routerContext?: RouterContext,\n globalContext?: HypenGlobalContext\n ) {\n this.engine = engine;\n this.definition = definition;\n this.routerContext = routerContext;\n this.globalContext = globalContext;\n\n // Create observable state that sends only changed paths and values to engine\n this.state = createObservableState<T>(definition.initialState as T & object, {\n onChange: (change: StateChange) => {\n // Send only the changed paths and their new values (not the whole state)\n this.engine.notifyStateChange(change.paths, change.newValues);\n // Notify all registered callbacks\n this.stateChangeCallbacks.forEach(cb => cb());\n },\n });\n\n // Register with engine (initial state registration)\n this.engine.setModule(\n definition.name || \"AnonymousModule\",\n definition.actions,\n definition.stateKeys,\n getStateSnapshot(this.state)\n );\n\n // Register action handlers with flexible parameter support\n for (const [actionName, handler] of definition.handlers.onAction) {\n console.log(`[ModuleInstance] Registering action handler: ${actionName} for module ${definition.name}`);\n this.engine.onAction(actionName, async (action: Action) => {\n console.log(`[ModuleInstance] Action handler fired: ${actionName}`, action);\n\n const actionCtx: ActionContext = {\n name: action.name,\n payload: action.payload,\n sender: action.sender,\n };\n\n const next: ActionNext = {\n router: this.routerContext?.root || (null as any),\n };\n\n const context: GlobalContext | undefined = this.globalContext\n ? this.createGlobalContextAPI()\n : undefined;\n\n try {\n await handler({\n action: actionCtx,\n state: this.state,\n next,\n context: context!,\n });\n console.log(`[ModuleInstance] Action handler completed: ${actionName}`);\n } catch (error) {\n console.error(`[ModuleInstance] Action handler error for ${actionName}:`, error);\n }\n });\n }\n\n // Call onCreated\n this.callCreatedHandler();\n }\n\n /**\n * Create the global context API for this module\n */\n private createGlobalContextAPI(): GlobalContext {\n if (!this.globalContext) {\n throw new Error(\"Global context not available\");\n }\n\n const ctx = this.globalContext;\n const api: GlobalContext = {\n getModule: (id: string) => ctx.getModule(id),\n hasModule: (id: string) => ctx.hasModule(id),\n getModuleIds: () => ctx.getModuleIds(),\n getGlobalState: () => ctx.getGlobalState(),\n emit: (event: string, payload?: any) => ctx.emit(event, payload),\n on: (event: string, handler: (payload?: any) => void) =>\n ctx.on(event, handler),\n };\n\n // Expose router and hypen engine for built-in components (if available)\n if ((ctx as any).__router) {\n api.__router = (ctx as any).__router;\n }\n if ((ctx as any).__hypenEngine) {\n (api as any).__hypenEngine = (ctx as any).__hypenEngine;\n }\n\n return api;\n }\n\n /**\n * Call the onCreated handler\n */\n private async callCreatedHandler(): Promise<void> {\n if (this.definition.handlers.onCreated) {\n const context = this.globalContext ? this.createGlobalContextAPI() : undefined;\n await this.definition.handlers.onCreated(this.state, context);\n }\n }\n\n /**\n * Register a callback to be notified when state changes\n */\n onStateChange(callback: () => void): void {\n this.stateChangeCallbacks.push(callback);\n }\n\n /**\n * Destroy the module instance\n */\n async destroy(): Promise<void> {\n if (this.isDestroyed) return;\n\n if (this.definition.handlers.onDestroyed) {\n await this.definition.handlers.onDestroyed(this.state);\n }\n\n this.isDestroyed = true;\n }\n\n /**\n * Get the current state (returns a snapshot)\n */\n getState(): T {\n return getStateSnapshot(this.state);\n }\n\n /**\n * Get the live observable state\n */\n getLiveState(): T {\n return this.state;\n }\n\n /**\n * Update state directly (merges with existing state)\n */\n updateState(patch: Partial<T>): void {\n Object.assign(this.state, patch);\n }\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "220ACA4FDA4DC86164756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,114 @@
1
+ import {
2
+ TypedEventEmitter
3
+ } from "./events.js";
4
+ import"../chunk-5va59f7m.js";
5
+
6
+ // src/context.ts
7
+ class HypenGlobalContext {
8
+ modules = new Map;
9
+ typedEvents;
10
+ legacyEventBus = new Map;
11
+ constructor() {
12
+ this.typedEvents = new TypedEventEmitter;
13
+ }
14
+ get events() {
15
+ return this.typedEvents;
16
+ }
17
+ registerModule(id, instance) {
18
+ if (this.modules.has(id)) {
19
+ console.warn(`Module "${id}" is already registered. Overwriting.`);
20
+ }
21
+ this.modules.set(id, instance);
22
+ console.log(`Registered module: ${id}`);
23
+ }
24
+ unregisterModule(id) {
25
+ this.modules.delete(id);
26
+ console.log(`Unregistered module: ${id}`);
27
+ }
28
+ getModule(id) {
29
+ const module = this.modules.get(id);
30
+ if (!module) {
31
+ throw new Error(`Module "${id}" not found. Available modules: ${Array.from(this.modules.keys()).join(", ")}`);
32
+ }
33
+ return {
34
+ state: module.getLiveState(),
35
+ setState: (patch) => module.updateState(patch),
36
+ getState: () => module.getState()
37
+ };
38
+ }
39
+ hasModule(id) {
40
+ return this.modules.has(id);
41
+ }
42
+ getModuleIds() {
43
+ return Array.from(this.modules.keys());
44
+ }
45
+ getGlobalState() {
46
+ const state = {};
47
+ this.modules.forEach((module, id) => {
48
+ state[id] = module.getState();
49
+ });
50
+ return state;
51
+ }
52
+ emit(event, payload) {
53
+ const handlers = this.legacyEventBus.get(event);
54
+ if (!handlers || handlers.size === 0) {
55
+ console.log(`Event "${event}" emitted but no listeners`);
56
+ } else {
57
+ console.log(`Emitting event: ${event}`, payload);
58
+ handlers.forEach((handler) => {
59
+ try {
60
+ handler(payload);
61
+ } catch (error) {
62
+ console.error(`Error in event handler for "${event}":`, error);
63
+ }
64
+ });
65
+ }
66
+ if (this.typedEvents.listenerCount(event) > 0) {
67
+ this.typedEvents.emit(event, payload);
68
+ }
69
+ }
70
+ on(event, handler) {
71
+ if (!this.legacyEventBus.has(event)) {
72
+ this.legacyEventBus.set(event, new Set);
73
+ }
74
+ const handlers = this.legacyEventBus.get(event);
75
+ handlers.add(handler);
76
+ console.log(`Listening to event: ${event}`);
77
+ return () => {
78
+ handlers.delete(handler);
79
+ if (handlers.size === 0) {
80
+ this.legacyEventBus.delete(event);
81
+ }
82
+ };
83
+ }
84
+ off(event, handler) {
85
+ const handlers = this.legacyEventBus.get(event);
86
+ if (handlers) {
87
+ handlers.delete(handler);
88
+ if (handlers.size === 0) {
89
+ this.legacyEventBus.delete(event);
90
+ }
91
+ }
92
+ }
93
+ clearEvent(event) {
94
+ this.legacyEventBus.delete(event);
95
+ }
96
+ clearAllEvents() {
97
+ this.legacyEventBus.clear();
98
+ }
99
+ debug() {
100
+ return {
101
+ modules: this.getModuleIds(),
102
+ events: Array.from(this.legacyEventBus.keys()),
103
+ typedEvents: this.typedEvents.eventNames(),
104
+ state: this.getGlobalState()
105
+ };
106
+ }
107
+ }
108
+ export {
109
+ HypenGlobalContext
110
+ };
111
+
112
+ export { HypenGlobalContext };
113
+
114
+ //# debugId=C15ABCA30BB35BCF64756E2164756E21