@hypen-space/core 0.4.980 → 0.5.3
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 +5 -8
- package/dist/a11y.d.ts +82 -0
- package/dist/app.js +13 -1168
- package/dist/app.js.map +3 -9
- package/dist/chunk-00zt3w6e.js +58 -0
- package/dist/chunk-00zt3w6e.js.map +10 -0
- package/dist/chunk-3zvyth50.js +87 -0
- package/dist/chunk-3zvyth50.js.map +10 -0
- package/dist/chunk-5gtx3pza.js +11 -0
- package/dist/chunk-5gtx3pza.js.map +9 -0
- package/dist/chunk-7222131a.js +191 -0
- package/dist/chunk-7222131a.js.map +10 -0
- package/dist/chunk-avchpwhf.js +200 -0
- package/dist/chunk-avchpwhf.js.map +10 -0
- package/dist/chunk-ec0tgy9a.js +154 -0
- package/dist/chunk-ec0tgy9a.js.map +10 -0
- package/dist/chunk-fnss4dm2.js +479 -0
- package/dist/chunk-fnss4dm2.js.map +10 -0
- package/dist/chunk-g2gz9pgg.js +133 -0
- package/dist/chunk-g2gz9pgg.js.map +10 -0
- package/dist/chunk-g72v6mmf.js +341 -0
- package/dist/chunk-g72v6mmf.js.map +10 -0
- package/dist/chunk-g7g3jxty.js +351 -0
- package/dist/chunk-g7g3jxty.js.map +10 -0
- package/dist/chunk-g830re2c.js +50 -0
- package/dist/chunk-g830re2c.js.map +10 -0
- package/dist/chunk-gtwh1sg7.js +127 -0
- package/dist/chunk-gtwh1sg7.js.map +10 -0
- package/dist/chunk-k12cwfst.js +72 -0
- package/dist/chunk-k12cwfst.js.map +10 -0
- package/dist/chunk-mbqqsz6r.js +128 -0
- package/dist/chunk-mbqqsz6r.js.map +10 -0
- package/dist/chunk-ne632swm.js +209 -0
- package/dist/chunk-ne632swm.js.map +10 -0
- package/dist/chunk-p3pj1bax.js +206 -0
- package/dist/chunk-p3pj1bax.js.map +10 -0
- package/dist/chunk-vshdk2pw.js +56 -0
- package/dist/chunk-vshdk2pw.js.map +10 -0
- package/dist/chunk-wp2ebn2m.js +51 -0
- package/dist/chunk-wp2ebn2m.js.map +10 -0
- package/dist/chunk-x4qv4jm9.js +88 -0
- package/dist/chunk-x4qv4jm9.js.map +10 -0
- package/dist/chunk-ycxp4drd.js +211 -0
- package/dist/chunk-ycxp4drd.js.map +10 -0
- package/dist/components/builtin.js +14 -1246
- package/dist/components/builtin.js.map +3 -10
- package/dist/context.js +7 -362
- package/dist/context.js.map +3 -6
- package/dist/datasource.js +5 -76
- package/dist/datasource.js.map +3 -4
- package/dist/disposable.js +20 -367
- package/dist/disposable.js.map +3 -5
- package/dist/engine-base.d.ts +38 -2
- package/dist/engine-base.js +45 -412
- package/dist/engine-base.js.map +4 -6
- package/dist/events.js +7 -285
- package/dist/events.js.map +3 -5
- package/dist/hypen.js +8 -71
- package/dist/hypen.js.map +3 -4
- package/dist/index.browser.js +58 -2152
- package/dist/index.browser.js.map +3 -16
- package/dist/index.d.ts +4 -0
- package/dist/index.js +175 -3057
- package/dist/index.js.map +5 -22
- package/dist/logger.js +16 -220
- package/dist/logger.js.map +3 -4
- package/dist/managed-router.js +12 -1367
- package/dist/managed-router.js.map +3 -10
- package/dist/portable.js +6 -70
- package/dist/portable.js.map +3 -4
- package/dist/remote/client.js +9 -1010
- package/dist/remote/client.js.map +3 -8
- package/dist/remote/index.d.ts +2 -0
- package/dist/remote/index.js +511 -1066
- package/dist/remote/index.js.map +4 -9
- package/dist/remote/remote-session.d.ts +245 -0
- package/dist/remote/session.js +5 -147
- package/dist/remote/session.js.map +3 -4
- package/dist/renderer.js +7 -271
- package/dist/renderer.js.map +3 -5
- package/dist/resolver.js +5 -484
- package/dist/resolver.js.map +3 -5
- package/dist/result.js +25 -211
- package/dist/result.js.map +3 -4
- package/dist/retry.js +10 -336
- package/dist/retry.js.map +3 -5
- package/dist/router.js +9 -807
- package/dist/router.js.map +3 -8
- package/dist/state.js +10 -274
- package/dist/state.js.map +3 -5
- package/dist/types.d.ts +129 -1
- package/dist/validate.d.ts +19 -0
- package/package.json +13 -1
- package/src/a11y.ts +127 -0
- package/src/engine-base.ts +87 -4
- package/src/index.ts +10 -0
- package/src/remote/index.ts +16 -0
- package/src/remote/remote-session.ts +998 -0
- package/src/types.ts +131 -1
- package/src/validate.ts +37 -0
package/dist/engine-base.js.map
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/
|
|
3
|
+
"sources": ["../src/engine-base.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Result Type for Error Handling\n *\n * A lightweight Result type for explicit error handling without exceptions.\n * Provides type-safe error propagation and composition.\n */\n\n/**\n * Represents either a successful value or an error\n */\nexport type Result<T, E = Error> =\n | { readonly ok: true; readonly value: T }\n | { readonly ok: false; readonly error: E };\n\n/**\n * Create a successful Result\n */\nexport function Ok<T>(value: T): Result<T, never> {\n return { ok: true, value };\n}\n\n/**\n * Create a failed Result\n */\nexport function Err<E>(error: E): Result<never, E> {\n return { ok: false, error };\n}\n\n/**\n * Check if a Result is Ok\n */\nexport function isOk<T, E>(result: Result<T, E>): result is { ok: true; value: T } {\n return result.ok;\n}\n\n/**\n * Check if a Result is Err\n */\nexport function isErr<T, E>(result: Result<T, E>): result is { ok: false; error: E } {\n return !result.ok;\n}\n\n/**\n * Wrap a Promise in a Result, catching any thrown errors\n */\nexport async function fromPromise<T, E = Error>(\n promise: Promise<T>,\n mapError?: (e: unknown) => E\n): Promise<Result<T, E>> {\n try {\n const value = await promise;\n return Ok(value);\n } catch (e) {\n if (mapError) {\n return Err(mapError(e));\n }\n return Err(e as E);\n }\n}\n\n/**\n * Wrap a synchronous function in a Result, catching any thrown errors\n */\nexport function fromTry<T, E = Error>(\n fn: () => T,\n mapError?: (e: unknown) => E\n): Result<T, E> {\n try {\n return Ok(fn());\n } catch (e) {\n if (mapError) {\n return Err(mapError(e));\n }\n return Err(e as E);\n }\n}\n\n/**\n * Map over a successful Result value\n */\nexport function map<T, U, E>(\n result: Result<T, E>,\n fn: (value: T) => U\n): Result<U, E> {\n if (result.ok) {\n return Ok(fn(result.value));\n }\n return result;\n}\n\n/**\n * Map over a failed Result error\n */\nexport function mapErr<T, E, F>(\n result: Result<T, E>,\n fn: (error: E) => F\n): Result<T, F> {\n if (!result.ok) {\n return Err(fn(result.error));\n }\n return result;\n}\n\n/**\n * Chain Results together (flatMap)\n */\nexport function flatMap<T, U, E>(\n result: Result<T, E>,\n fn: (value: T) => Result<U, E>\n): Result<U, E> {\n if (result.ok) {\n return fn(result.value);\n }\n return result;\n}\n\n/**\n * Unwrap a Result, throwing if it's an error\n */\nexport function unwrap<T, E>(result: Result<T, E>): T {\n if (result.ok) {\n return result.value;\n }\n throw result.error;\n}\n\n/**\n * Unwrap a Result with a default value\n */\nexport function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {\n if (result.ok) {\n return result.value;\n }\n return defaultValue;\n}\n\n/**\n * Unwrap a Result with a lazy default value\n */\nexport function unwrapOrElse<T, E>(result: Result<T, E>, fn: (error: E) => T): T {\n if (result.ok) {\n return result.value;\n }\n return fn(result.error);\n}\n\n/**\n * Match on a Result, providing handlers for both cases\n */\nexport function match<T, E, U>(\n result: Result<T, E>,\n handlers: {\n ok: (value: T) => U;\n err: (error: E) => U;\n }\n): U {\n if (result.ok) {\n return handlers.ok(result.value);\n }\n return handlers.err(result.error);\n}\n\n/**\n * Combine multiple Results into a single Result containing an array\n * Returns the first error encountered, or Ok with all values\n */\nexport function all<T, E>(results: Result<T, E>[]): Result<T[], E> {\n const values: T[] = [];\n for (const result of results) {\n if (!result.ok) {\n return result;\n }\n values.push(result.value);\n }\n return Ok(values);\n}\n\n/**\n * Base class for typed errors with context\n */\nexport class HypenError extends Error {\n readonly code: string;\n readonly context?: Record<string, unknown>;\n override readonly cause?: Error;\n\n constructor(\n code: string,\n message: string,\n options?: { context?: Record<string, unknown>; cause?: Error }\n ) {\n super(message);\n this.name = 'HypenError';\n this.code = code;\n this.context = options?.context;\n this.cause = options?.cause;\n\n // Maintain proper prototype chain\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Error thrown when an action handler fails\n */\nexport class ActionError extends HypenError {\n readonly actionName: string;\n\n constructor(actionName: string, cause?: unknown) {\n super(\n 'ACTION_ERROR',\n `Action handler \"${actionName}\" failed: ${cause instanceof Error ? cause.message : String(cause)}`,\n {\n context: { actionName },\n cause: cause instanceof Error ? cause : undefined,\n }\n );\n this.name = 'ActionError';\n this.actionName = actionName;\n }\n}\n\n/**\n * Error thrown when a connection fails\n */\nexport class ConnectionError extends HypenError {\n readonly url: string;\n readonly attempt?: number;\n\n constructor(url: string, cause?: unknown, attempt?: number) {\n super(\n 'CONNECTION_ERROR',\n `Connection to \"${url}\" failed${attempt ? ` (attempt ${attempt})` : ''}: ${\n cause instanceof Error ? cause.message : String(cause)\n }`,\n {\n context: { url, attempt },\n cause: cause instanceof Error ? cause : undefined,\n }\n );\n this.name = 'ConnectionError';\n this.url = url;\n this.attempt = attempt;\n }\n}\n\n/**\n * Error thrown when state operations fail\n */\nexport class StateError extends HypenError {\n readonly path?: string;\n\n constructor(message: string, path?: string, cause?: unknown) {\n super('STATE_ERROR', message, {\n context: { path },\n cause: cause instanceof Error ? cause : undefined,\n });\n this.name = 'StateError';\n this.path = path;\n }\n}\n\n/**\n * Error thrown when parsing Hypen DSL source fails\n */\nexport class ParseError extends HypenError {\n readonly source?: string;\n\n constructor(message: string, source?: string, cause?: unknown) {\n super('PARSE_ERROR', message, {\n context: { source },\n cause: cause instanceof Error ? cause : undefined,\n });\n this.name = 'ParseError';\n this.source = source;\n }\n}\n\n/**\n * Error thrown when rendering fails\n */\nexport class RenderError extends HypenError {\n constructor(message: string, cause?: unknown) {\n super('RENDER_ERROR', message, {\n cause: cause instanceof Error ? cause : undefined,\n });\n this.name = 'RenderError';\n }\n}\n\n/**\n * Classify a WASM engine error string into the appropriate HypenError subclass.\n * The engine returns JsValue error strings with known prefixes.\n */\nexport function classifyEngineError(err: unknown): HypenError {\n // Handle structured WASM errors: { type: string, message: string }\n if (err && typeof err === 'object' && 'message' in err && 'type' in err) {\n const structured = err as { type: string; message: string };\n switch (structured.type) {\n case 'parseError': return new ParseError(structured.message);\n case 'stateError': return new StateError(structured.message);\n case 'renderError': return new RenderError(structured.message);\n case 'actionError': return new HypenError('ACTION_ERROR', structured.message);\n default: return new HypenError('UNKNOWN_ERROR', structured.message);\n }\n }\n const message = err instanceof Error ? err.message : String(err);\n\n if (message.startsWith('Parse error:')) {\n return new ParseError(message);\n }\n if (message.startsWith('Invalid state:') || message.startsWith('Invalid state patch:')) {\n return new StateError(message);\n }\n if (message.startsWith('Parent node not found:')) {\n return new RenderError(message);\n }\n\n return new RenderError(message);\n}\n",
|
|
6
|
-
"/**\n * Configurable Debug Logger\n *\n * Provides environment-aware logging that can be disabled in production.\n * Supports log levels, tagged output, and performance timing.\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"none\";\n\nexport interface LoggerConfig {\n /** Minimum log level (default: \"debug\" in dev, \"error\" in prod) */\n level: LogLevel;\n /** Enable colored output (default: true) */\n colors: boolean;\n /** Include timestamps (default: false) */\n timestamps: boolean;\n /** Custom log handler (default: console) */\n handler?: LogHandler;\n}\n\nexport interface LogHandler {\n debug(tag: string, ...args: unknown[]): void;\n info(tag: string, ...args: unknown[]): void;\n warn(tag: string, ...args: unknown[]): void;\n error(tag: string, ...args: unknown[]): void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst LOG_LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n none: 4,\n};\n\nconst LOG_LEVEL_COLORS: Record<Exclude<LogLevel, \"none\">, string> = {\n debug: \"\\x1b[36m\", // Cyan\n info: \"\\x1b[32m\", // Green\n warn: \"\\x1b[33m\", // Yellow\n error: \"\\x1b[31m\", // Red\n};\n\nconst RESET_COLOR = \"\\x1b[0m\";\n\n// ============================================================================\n// Global Configuration\n// ============================================================================\n\n/**\n * Detect if running in production environment\n */\nfunction isProduction(): boolean {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env.NODE_ENV === \"production\";\n }\n return false;\n}\n\n/**\n * Default configuration\n */\nlet config: LoggerConfig = {\n level: isProduction() ? \"error\" : \"info\",\n colors: true,\n timestamps: false,\n};\n\n// ============================================================================\n// Configuration API\n// ============================================================================\n\n/**\n * Set the global log level\n */\nexport function setLogLevel(level: LogLevel): void {\n config.level = level;\n}\n\n/**\n * Get the current log level\n */\nexport function getLogLevel(): LogLevel {\n return config.level;\n}\n\n/**\n * Configure the logger\n */\nexport function configureLogger(options: Partial<LoggerConfig>): void {\n config = { ...config, ...options };\n}\n\n/**\n * Enable all logging (sets level to \"debug\")\n */\nexport function enableLogging(): void {\n config.level = \"debug\";\n}\n\n/**\n * Disable all logging (sets level to \"none\")\n */\nexport function disableLogging(): void {\n config.level = \"none\";\n}\n\n/**\n * Enable debug mode - alias for enableLogging()\n * Call this at app startup to see all debug logs\n *\n * @example\n * ```typescript\n * import { setDebugMode } from \"@hypen-space/core\";\n * setDebugMode(true);\n * ```\n */\nexport function setDebugMode(enabled: boolean): void {\n config.level = enabled ? \"debug\" : \"error\";\n}\n\n/**\n * Check if debug mode is enabled\n */\nexport function isDebugMode(): boolean {\n return config.level === \"debug\";\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVEL_ORDER[level] >= LOG_LEVEL_ORDER[config.level];\n}\n\nfunction formatTag(tag: string, level: LogLevel): string {\n const timestamp = config.timestamps ? `${new Date().toISOString()} ` : \"\";\n\n if (config.colors && level !== \"none\") {\n const color = LOG_LEVEL_COLORS[level as Exclude<LogLevel, \"none\">];\n return `${timestamp}${color}[${tag}]${RESET_COLOR}`;\n }\n\n return `${timestamp}[${tag}]`;\n}\n\n// ============================================================================\n// Logger Class\n// ============================================================================\n\n/**\n * Tagged logger instance\n *\n * @example\n * ```typescript\n * const log = createLogger(\"MyComponent\");\n * log.debug(\"initialized with\", { props });\n * log.error(\"failed to load\", error);\n * ```\n */\nexport class Logger {\n private readonly tag: string;\n\n constructor(tag: string) {\n this.tag = tag;\n }\n\n debug(...args: unknown[]): void {\n if (!shouldLog(\"debug\")) return;\n\n if (config.handler) {\n config.handler.debug(this.tag, ...args);\n } else {\n console.log(formatTag(this.tag, \"debug\"), ...args);\n }\n }\n\n info(...args: unknown[]): void {\n if (!shouldLog(\"info\")) return;\n\n if (config.handler) {\n config.handler.info(this.tag, ...args);\n } else {\n console.info(formatTag(this.tag, \"info\"), ...args);\n }\n }\n\n warn(...args: unknown[]): void {\n if (!shouldLog(\"warn\")) return;\n\n if (config.handler) {\n config.handler.warn(this.tag, ...args);\n } else {\n console.warn(formatTag(this.tag, \"warn\"), ...args);\n }\n }\n\n error(...args: unknown[]): void {\n if (!shouldLog(\"error\")) return;\n\n if (config.handler) {\n config.handler.error(this.tag, ...args);\n } else {\n console.error(formatTag(this.tag, \"error\"), ...args);\n }\n }\n\n /**\n * Time a function execution\n */\n time<T>(label: string, fn: () => T): T {\n if (!shouldLog(\"debug\")) {\n return fn();\n }\n\n const start = performance.now();\n try {\n return fn();\n } finally {\n const duration = performance.now() - start;\n this.debug(`${label}: ${duration.toFixed(2)}ms`);\n }\n }\n\n /**\n * Time an async function execution\n */\n async timeAsync<T>(label: string, fn: () => Promise<T>): Promise<T> {\n if (!shouldLog(\"debug\")) {\n return fn();\n }\n\n const start = performance.now();\n try {\n return await fn();\n } finally {\n const duration = performance.now() - start;\n this.debug(`${label}: ${duration.toFixed(2)}ms`);\n }\n }\n\n /**\n * Create a child logger with additional context\n */\n child(subTag: string): Logger {\n return new Logger(`${this.tag}:${subTag}`);\n }\n\n /**\n * Conditionally log based on a condition\n */\n debugIf(condition: boolean, ...args: unknown[]): void {\n if (condition) this.debug(...args);\n }\n\n warnIf(condition: boolean, ...args: unknown[]): void {\n if (condition) this.warn(...args);\n }\n\n errorIf(condition: boolean, ...args: unknown[]): void {\n if (condition) this.error(...args);\n }\n\n /**\n * Log once (useful for deprecation warnings)\n */\n private loggedOnce = new Set<string>();\n\n warnOnce(key: string, ...args: unknown[]): void {\n if (this.loggedOnce.has(key)) return;\n this.loggedOnce.add(key);\n this.warn(...args);\n }\n\n debugOnce(key: string, ...args: unknown[]): void {\n if (this.loggedOnce.has(key)) return;\n this.loggedOnce.add(key);\n this.debug(...args);\n }\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a tagged logger\n *\n * @example\n * ```typescript\n * const log = createLogger(\"Router\");\n * log.info(\"navigating to\", path);\n * ```\n */\nexport function createLogger(tag: string): Logger {\n return new Logger(tag);\n}\n\n// ============================================================================\n// Default Logger Instance\n// ============================================================================\n\n/**\n * Default logger for general use\n */\nexport const logger = createLogger(\"Hypen\");\n\n// ============================================================================\n// Shorthand Functions (untagged)\n// ============================================================================\n\n/**\n * Shorthand logging functions for quick use\n * Prefer createLogger() for component-specific logging\n */\nexport const log = {\n debug: (tag: string, ...args: unknown[]): void => {\n if (!shouldLog(\"debug\")) return;\n console.log(formatTag(tag, \"debug\"), ...args);\n },\n\n info: (tag: string, ...args: unknown[]): void => {\n if (!shouldLog(\"info\")) return;\n console.info(formatTag(tag, \"info\"), ...args);\n },\n\n warn: (tag: string, ...args: unknown[]): void => {\n if (!shouldLog(\"warn\")) return;\n console.warn(formatTag(tag, \"warn\"), ...args);\n },\n\n error: (tag: string, ...args: unknown[]): void => {\n if (!shouldLog(\"error\")) return;\n console.error(formatTag(tag, \"error\"), ...args);\n },\n};\n\n// ============================================================================\n// Predefined Loggers for Framework Components\n// ============================================================================\n\nexport const frameworkLoggers = {\n hypen: createLogger(\"Hypen\"),\n engine: createLogger(\"Engine\"),\n router: createLogger(\"Router\"),\n state: createLogger(\"State\"),\n events: createLogger(\"Events\"),\n remote: createLogger(\"Remote\"),\n renderer: createLogger(\"Renderer\"),\n module: createLogger(\"Module\"),\n lifecycle: createLogger(\"Lifecycle\"),\n loader: createLogger(\"Loader\"),\n context: createLogger(\"Context\"),\n discovery: createLogger(\"Discovery\"),\n plugin: createLogger(\"Plugin\"),\n canvas: createLogger(\"Canvas\"),\n debug: createLogger(\"Debug\"),\n};\n",
|
|
7
|
-
"/**\n * Abstract base class for Hypen WASM engine wrappers.\n *\n * The Hypen engine is distributed as a wasm-bindgen module — two builds:\n *\n * - `wasm-node` (bundler target) — used by `@hypen-space/server` on Node/Bun\n * - `wasm-browser` (web target) — used by `@hypen-space/web-engine` in browsers\n *\n * Both builds expose an identical `WasmEngine` class; the only genuine\n * platform differences are:\n *\n * 1. How the WASM module is *instantiated*. Node can synchronously `new\n * WasmEngine()` (the bundler target auto-initializes); the browser\n * target needs an async dynamic import of the JS glue code and an\n * explicit `wasm_init(url)` call before any `new WasmEngine()`.\n *\n * 2. How host state is *unwrapped* before it crosses the WASM boundary.\n * Node can use `structuredClone` (with a `__getSnapshot` fast path for\n * Hypen's proxy-backed state); the browser path does a\n * `JSON.parse(JSON.stringify())` round-trip plus a Map-to-Object\n * conversion for the native Map values that the wasm-bindgen browser\n * target returns in action payloads.\n *\n * Everything else — method wrappers, error classification, callback wiring,\n * revision plumbing — is identical between the two. That shared surface\n * lives here.\n *\n * Subclasses implement two abstract hooks:\n *\n * - `init(options?): Promise<void>` — platform-specific WASM setup. Must\n * assign `this.wasmEngine` and set `this.initialized = true` on success.\n *\n * - `unwrapForWasm<T>(value: T): T` — platform-specific proxy-to-plain\n * conversion. Called before any value crosses into WASM.\n */\n\nimport { frameworkLoggers } from \"./logger.js\";\nimport { classifyEngineError } from \"./result.js\";\nimport type {\n Patch,\n Action,\n RenderCallback,\n ActionHandler,\n ComponentResolver,\n} from \"./types.js\";\n\nconst log = frameworkLoggers.engine;\n\n/**\n * Shared base wrapping a wasm-bindgen `WasmEngine`. `any` here is load-\n * bearing: the concrete type is `WasmEngine` from either the `wasm-node`\n * or `wasm-browser` build, and those are separate generated `.d.ts`\n * files that core cannot (and should not) depend on. Subclasses keep\n * their own typed reference if they want stricter checking locally.\n */\nexport abstract class BaseEngine {\n protected wasmEngine: any = null;\n protected initialized = false;\n\n /**\n * Initialize the WASM module. Platform-specific.\n *\n * Must assign `this.wasmEngine` and set `this.initialized = true`.\n * Idempotent: must early-return if already initialized.\n */\n abstract init(options?: unknown): Promise<void>;\n\n /**\n * Convert a host value (possibly a Proxy, possibly containing Maps,\n * possibly wrapped in Hypen's observable state) into a plain-object\n * form safe to pass across the WASM boundary.\n *\n * Called on every `updateState` / `updateStateSparse` / `renderInto`\n * / `setContext` / `registerModule` entry point.\n */\n protected abstract unwrapForWasm<T>(value: T): T;\n\n /**\n * Guard that throws if the engine hasn't been initialized.\n * Returns the underlying WASM engine for chained access.\n */\n protected 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(\n (componentName: string, contextPath: string | null) => {\n return resolver(componentName, contextPath);\n },\n );\n }\n\n /**\n * Parse and render Hypen DSL source code.\n * @throws {ParseError} if the source fails to parse\n * @throws {RenderError} if rendering fails\n */\n renderSource(source: string): void {\n const engine = this.ensureInitialized();\n try {\n engine.renderSource(source);\n } catch (err) {\n throw classifyEngineError(err);\n }\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 * @throws {ParseError} if the source fails to parse\n * @throws {RenderError} if the parent node is not found or rendering fails\n */\n renderInto(\n source: string,\n parentNodeId: string,\n state: Record<string, any>,\n ): void {\n const engine = this.ensureInitialized();\n try {\n engine.renderInto(source, parentNodeId, this.unwrapForWasm(state));\n } catch (err) {\n throw classifyEngineError(err);\n }\n }\n\n /**\n * Apply a sparse state update.\n *\n * @param scope Lowercase module name to target a named module registered\n * via `registerModule`. Pass `null` (or empty string) to\n * target the primary module set via `setModule`.\n * @param paths Changed state paths (relative to the targeted module).\n * @param values Map of `path -> new value`.\n * @throws {StateError} if the state patch is invalid\n */\n updateStateSparse(\n scope: string | null,\n paths: string[],\n values: Record<string, any>,\n ): void {\n const engine = this.ensureInitialized();\n\n if (paths.length === 0) {\n return;\n }\n\n try {\n engine.updateStateSparse(scope ?? \"\", paths, this.unwrapForWasm(values));\n } catch (err) {\n throw classifyEngineError(err);\n }\n log.debug(\"State changed (sparse):\", { scope, paths });\n }\n\n /**\n * Apply a full-state patch. See [updateStateSparse] for `scope` semantics.\n * Prefer the sparse form when only a few paths changed.\n */\n updateState(scope: string | null, statePatch: Record<string, any>): void {\n const engine = this.ensureInitialized();\n engine.updateState(scope ?? \"\", this.unwrapForWasm(statePatch));\n }\n\n /**\n * Dispatch an action.\n * @throws {HypenError} if the action dispatch fails\n */\n dispatchAction(name: string, payload?: any): void {\n const engine = this.ensureInitialized();\n try {\n engine.dispatchAction(name, payload ?? null);\n } catch (err) {\n throw classifyEngineError(err);\n }\n }\n\n /**\n * Register an action handler. Errors thrown synchronously or via rejected\n * promises are caught and logged at the framework level; caller-side error\n * recovery should happen inside `handler`.\n *\n * Action payloads may contain platform-specific native values (e.g. Maps\n * in the browser target). Subclasses can override `normalizeAction` to\n * pre-process the action before calling the user handler.\n */\n onAction(actionName: string, handler: ActionHandler): void {\n const engine = this.ensureInitialized();\n engine.onAction(actionName, (action: Action) => {\n const normalized = this.normalizeAction(action);\n Promise.resolve(handler(normalized)).catch((err) => {\n log.error(\"Action handler error:\", err);\n });\n });\n }\n\n /**\n * Platform hook: normalize an incoming action before the user handler\n * sees it. Default identity; subclasses can override to unwrap native\n * values (e.g. browser Maps in action payloads).\n */\n protected normalizeAction(action: Action): Action {\n return action;\n }\n\n /**\n * Parse a Hypen DSL source and return every `Router { Route ... }`\n * block found in it. The SDK uses this to auto-wire a ManagedRouter\n * against the template without the user having to repeat the route\n * table in code.\n *\n * `moduleScope` is the enclosing `module X { ... }` scope (lowercased)\n * — `null` for the document root. `elementNames` is BFS-ordered so\n * the SDK can pick the first name that matches a registered\n * `HypenApp` module (wrappers like Column / Row come before the\n * real route component).\n */\n discoverRouters(source: string): Array<{\n moduleScope: string | null;\n routes: Array<{ path: string; elementNames: string[] }>;\n }> {\n const engine = this.ensureInitialized();\n const raw = (engine as any).discoverRouters?.(source);\n if (!raw) return [];\n // wasm-bindgen returns Maps; normalize to plain objects for\n // ergonomic downstream consumption. The nested structures were\n // encoded with serde_wasm_bindgen so plain objects is the right\n // post-decode shape for most consumers.\n const mapToObj = (v: unknown): any => {\n if (v instanceof Map) {\n const obj: Record<string, unknown> = {};\n for (const [k, val] of v.entries()) obj[String(k)] = mapToObj(val);\n return obj;\n }\n if (Array.isArray(v)) return v.map(mapToObj);\n if (v && typeof v === \"object\") {\n const obj: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(v)) obj[k] = mapToObj(val);\n return obj;\n }\n return v;\n };\n const normalized = mapToObj(raw) as Array<{\n module_scope: string | null;\n moduleScope?: string | null;\n routes: Array<{\n path: string;\n element_names?: string[];\n elementNames?: string[];\n }>;\n }>;\n return normalized.map((r) => ({\n moduleScope: r.moduleScope ?? r.module_scope ?? null,\n routes: r.routes.map((route) => ({\n path: route.path,\n elementNames: route.elementNames ?? route.element_names ?? [],\n })),\n }));\n }\n\n /**\n * Initialize the primary 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 * Register a named module for multi-module apps.\n *\n * Unlike setModule which sets the primary module, this registers an\n * additional module whose state is scoped to `module <name> { ... }`\n * blocks in the DSL.\n */\n registerModule(\n name: string,\n actions: string[],\n stateKeys: string[],\n initialState: Record<string, any>,\n ): void {\n const engine = this.ensureInitialized();\n engine.registerModule(\n name,\n actions,\n stateKeys,\n this.unwrapForWasm(initialState),\n );\n }\n\n /**\n * Get the current revision number.\n *\n * Note: the underlying WASM builder returns `bigint` in some targets\n * and `number` in others; this normalizes to `number` for consumer\n * ergonomics (revision counts don't exceed 2^53).\n */\n getRevision(): number {\n const engine = this.ensureInitialized();\n return Number(engine.getRevision());\n }\n\n /**\n * Clear resolved components and caches, preserving primitives and resolver.\n * Call before renderSource() during hot-reload so components are re-resolved\n * from fresh source files.\n */\n clearResolvedComponents(): void {\n const engine = this.ensureInitialized();\n engine.clearResolvedComponents();\n }\n\n /**\n * Clear the engine tree.\n */\n clearTree(): void {\n const engine = this.ensureInitialized();\n engine.clearTree();\n }\n\n /**\n * Full reset: clears tree, module, component registry, dependencies,\n * and revision. Render callback and component resolver are preserved.\n */\n reset(): void {\n const engine = this.ensureInitialized();\n engine.reset();\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 // ── Data Source Context ────────────────────────────────────────\n\n /**\n * Set (or replace) a named data source context.\n *\n * Registers the provider in the dependency graph, stores the data,\n * and re-renders every node bound to `$name.*`.\n *\n * @param name - Provider name (e.g., \"spacetime\", \"firebase\")\n * @param data - Full state object for this provider\n */\n setContext(name: string, data: Record<string, unknown>): void {\n const engine = this.ensureInitialized();\n try {\n engine.setContext(name, this.unwrapForWasm(data));\n } catch (err) {\n throw classifyEngineError(err);\n }\n log.debug(`Data source \"${name}\" context set`);\n }\n\n /**\n * Remove a data source context entirely.\n * Drops the provider's state and re-renders bound nodes (they resolve to null).\n */\n removeContext(name: string): void {\n const engine = this.ensureInitialized();\n engine.removeContext(name);\n }\n\n // ── Resource System ─────────────────────────────────────────────────\n\n /**\n * Register resources (name → raw SVG string) with the engine.\n *\n * Each SVG is parsed by the WASM engine. When the engine encounters\n * `Icon(@resources.heart)` in the DSL, it resolves the name from registered\n * resources and injects SVG path data into the Create patch props.\n *\n * @param map - Flat map of resource name to raw SVG string\n */\n registerResources(map: Record<string, string>): void {\n const engine = this.ensureInitialized();\n engine.registerResources(map);\n log.debug(`Resources registered (${Object.keys(map).length} entries)`);\n }\n}\n"
|
|
5
|
+
"/**\n * Abstract base class for Hypen WASM engine wrappers.\n *\n * The Hypen engine is distributed as a wasm-bindgen module — two builds:\n *\n * - `wasm-node` (bundler target) — used by `@hypen-space/server` on Node/Bun\n * - `wasm-browser` (web target) — used by `@hypen-space/web-engine` in browsers\n *\n * Both builds expose an identical `WasmEngine` class; the only genuine\n * platform differences are:\n *\n * 1. How the WASM module is *instantiated*. Node can synchronously `new\n * WasmEngine()` (the bundler target auto-initializes); the browser\n * target needs an async dynamic import of the JS glue code and an\n * explicit `wasm_init(url)` call before any `new WasmEngine()`.\n *\n * 2. How host state is *unwrapped* before it crosses the WASM boundary.\n * Node can use `structuredClone` (with a `__getSnapshot` fast path for\n * Hypen's proxy-backed state); the browser path does a\n * `JSON.parse(JSON.stringify())` round-trip plus a Map-to-Object\n * conversion for the native Map values that the wasm-bindgen browser\n * target returns in action payloads.\n *\n * Everything else — method wrappers, error classification, callback wiring,\n * revision plumbing — is identical between the two. That shared surface\n * lives here.\n *\n * Subclasses implement two abstract hooks:\n *\n * - `init(options?): Promise<void>` — platform-specific WASM setup. Must\n * assign `this.wasmEngine` and set `this.initialized = true` on success.\n *\n * - `unwrapForWasm<T>(value: T): T` — platform-specific proxy-to-plain\n * conversion. Called before any value crosses into WASM.\n */\n\nimport { frameworkLoggers } from \"./logger.js\";\nimport { classifyEngineError } from \"./result.js\";\nimport type {\n Patch,\n Action,\n RenderCallback,\n ActionHandler,\n ComponentResolver,\n} from \"./types.js\";\n\nconst log = frameworkLoggers.engine;\n\n/**\n * Recursively convert wasm-bindgen `Map` values into plain objects.\n *\n * The web-target WASM returns action payloads (and nested values) as `Map`\n * instances; user handlers expect plain objects. Only plain objects\n * (`constructor === Object`), arrays, and Maps are descended into — class\n * instances, `Date`, etc. are passed through untouched.\n */\nfunction mapToPlainObject(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] = mapToPlainObject(val);\n }\n return obj;\n }\n if (Array.isArray(value)) {\n return value.map(mapToPlainObject);\n }\n 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] = mapToPlainObject(val);\n }\n return obj;\n }\n return value;\n}\n\n/**\n * Shared base wrapping a wasm-bindgen `WasmEngine`. `any` here is load-\n * bearing: the concrete type is `WasmEngine` from either the `wasm-node`\n * or `wasm-browser` build, and those are separate generated `.d.ts`\n * files that core cannot (and should not) depend on. Subclasses keep\n * their own typed reference if they want stricter checking locally.\n */\nexport abstract class BaseEngine {\n protected wasmEngine: any = null;\n protected initialized = false;\n\n /**\n * Component names the resolver was asked for and returned `null` on — i.e.\n * names that are neither a registered primitive (the engine checks those\n * first and never consults the resolver for them) nor resolvable to a\n * template. Each such name produces an opaque `Create` patch the renderer\n * drops. Tracked so a miss is warned about once and can be asserted on in\n * tests. See `getUnresolvedComponents`.\n */\n private unresolvedComponents = new Set<string>();\n\n /**\n * Initialize the WASM module. Platform-specific.\n *\n * Must assign `this.wasmEngine` and set `this.initialized = true`.\n * Idempotent: must early-return if already initialized.\n */\n abstract init(options?: unknown): Promise<void>;\n\n /**\n * Convert a host value (possibly a Proxy, possibly containing Maps,\n * possibly wrapped in Hypen's observable state) into a plain-object\n * form safe to pass across the WASM boundary.\n *\n * Called on every `updateState` / `updateStateSparse` / `renderInto`\n * / `setContext` / `registerModule` entry point.\n */\n protected abstract unwrapForWasm<T>(value: T): T;\n\n /**\n * Guard that throws if the engine hasn't been initialized.\n * Returns the underlying WASM engine for chained access.\n */\n protected 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 * The resolver is wrapped to detect \"resolver misses\": the engine only\n * consults the resolver for element types that are NOT registered\n * primitives, so a `null` return means the name resolves to nothing and\n * the engine will emit an opaque `Create` the renderer silently drops\n * (e.g. an anonymous component that never got registered). The first miss\n * for each unique name is logged with actionable guidance; every miss is\n * recorded for `getUnresolvedComponents()` / test assertions.\n */\n setComponentResolver(resolver: ComponentResolver): void {\n const engine = this.ensureInitialized();\n engine.setComponentResolver(\n (componentName: string, contextPath: string | null) => {\n const resolved = resolver(componentName, contextPath);\n if (resolved == null) {\n if (!this.unresolvedComponents.has(componentName)) {\n this.unresolvedComponents.add(componentName);\n log.warn(\n `Component \"${componentName}\" did not resolve: it is not a ` +\n `registered primitive and the component resolver returned null. ` +\n `The engine will emit an opaque Create for it and the renderer ` +\n `will drop it. Did you forget to register/.module(...) the ` +\n `component, or is its name misspelled in the template?`,\n );\n }\n }\n return resolved;\n },\n );\n }\n\n /**\n * Names the component resolver has been asked for and failed to resolve\n * this session (see `setComponentResolver`). Useful as a CI / smoke-test\n * assertion — an empty array means every referenced component resolved to\n * a primitive or a template.\n */\n getUnresolvedComponents(): string[] {\n return [...this.unresolvedComponents];\n }\n\n /**\n * Parse and render Hypen DSL source code.\n * @throws {ParseError} if the source fails to parse\n * @throws {RenderError} if rendering fails\n */\n renderSource(source: string): void {\n const engine = this.ensureInitialized();\n try {\n engine.renderSource(source);\n } catch (err) {\n throw classifyEngineError(err);\n }\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 * @throws {ParseError} if the source fails to parse\n * @throws {RenderError} if the parent node is not found or rendering fails\n */\n renderInto(\n source: string,\n parentNodeId: string,\n state: Record<string, any>,\n ): void {\n const engine = this.ensureInitialized();\n try {\n engine.renderInto(source, parentNodeId, this.unwrapForWasm(state));\n } catch (err) {\n throw classifyEngineError(err);\n }\n }\n\n /**\n * Apply a sparse state update.\n *\n * @param scope Lowercase module name to target a named module registered\n * via `registerModule`. Pass `null` (or empty string) to\n * target the primary module set via `setModule`.\n * @param paths Changed state paths (relative to the targeted module).\n * @param values Map of `path -> new value`.\n * @throws {StateError} if the state patch is invalid\n */\n updateStateSparse(\n scope: string | null,\n paths: string[],\n values: Record<string, any>,\n ): void {\n const engine = this.ensureInitialized();\n\n if (paths.length === 0) {\n return;\n }\n\n try {\n engine.updateStateSparse(scope ?? \"\", paths, this.unwrapForWasm(values));\n } catch (err) {\n throw classifyEngineError(err);\n }\n log.debug(\"State changed (sparse):\", { scope, paths });\n }\n\n /**\n * Apply a full-state patch. See [updateStateSparse] for `scope` semantics.\n * Prefer the sparse form when only a few paths changed.\n */\n updateState(scope: string | null, statePatch: Record<string, any>): void {\n const engine = this.ensureInitialized();\n engine.updateState(scope ?? \"\", this.unwrapForWasm(statePatch));\n }\n\n /**\n * Dispatch an action.\n * @throws {HypenError} if the action dispatch fails\n */\n dispatchAction(name: string, payload?: any): void {\n const engine = this.ensureInitialized();\n try {\n engine.dispatchAction(name, payload ?? null);\n } catch (err) {\n throw classifyEngineError(err);\n }\n }\n\n /**\n * Register an action handler. Errors thrown synchronously or via rejected\n * promises are caught and logged at the framework level; caller-side error\n * recovery should happen inside `handler`.\n *\n * Action payloads may contain platform-specific native values (e.g. Maps\n * in the browser target). Subclasses can override `normalizeAction` to\n * pre-process the action before calling the user handler.\n */\n onAction(actionName: string, handler: ActionHandler): void {\n const engine = this.ensureInitialized();\n engine.onAction(actionName, (action: Action) => {\n const normalized = this.normalizeAction(action);\n Promise.resolve(handler(normalized)).catch((err) => {\n log.error(\"Action handler error:\", err);\n });\n });\n }\n\n /**\n * Platform hook: normalize an incoming action before the user handler\n * sees it.\n *\n * The default converts any `Map` instances in the payload into plain\n * objects (deeply). This is the landmine the wasm-bindgen **web** target\n * sets: it returns structured action payloads as JS `Map`s, so a handler\n * reading `payload.to` gets `undefined` and `@router.push, to: \"/x\"`\n * silently no-ops. Every consumer of the web-target WASM — the browser\n * engine, a Cloudflare `CFEngine`, any future runtime — inherits the fix\n * here instead of rediscovering it.\n *\n * The wasm-bindgen **bundler** (node) target already returns plain\n * objects, so for it this is a harmless deep walk. Subclasses on that\n * target may override with an identity to skip the walk (see\n * `@hypen-space/server`).\n */\n protected normalizeAction(action: Action): Action {\n if (!action.payload) return action;\n return { ...action, payload: mapToPlainObject(action.payload) };\n }\n\n /**\n * Parse a Hypen DSL source and return every `Router { Route ... }`\n * block found in it. The SDK uses this to auto-wire a ManagedRouter\n * against the template without the user having to repeat the route\n * table in code.\n *\n * `moduleScope` is the enclosing `module X { ... }` scope (lowercased)\n * — `null` for the document root. `elementNames` is BFS-ordered so\n * the SDK can pick the first name that matches a registered\n * `HypenApp` module (wrappers like Column / Row come before the\n * real route component).\n */\n discoverRouters(source: string): Array<{\n moduleScope: string | null;\n routes: Array<{ path: string; elementNames: string[] }>;\n }> {\n const engine = this.ensureInitialized();\n const raw = (engine as any).discoverRouters?.(source);\n if (!raw) return [];\n // wasm-bindgen returns Maps; normalize to plain objects for\n // ergonomic downstream consumption. The nested structures were\n // encoded with serde_wasm_bindgen so plain objects is the right\n // post-decode shape for most consumers.\n const mapToObj = (v: unknown): any => {\n if (v instanceof Map) {\n const obj: Record<string, unknown> = {};\n for (const [k, val] of v.entries()) obj[String(k)] = mapToObj(val);\n return obj;\n }\n if (Array.isArray(v)) return v.map(mapToObj);\n if (v && typeof v === \"object\") {\n const obj: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(v)) obj[k] = mapToObj(val);\n return obj;\n }\n return v;\n };\n const normalized = mapToObj(raw) as Array<{\n module_scope: string | null;\n moduleScope?: string | null;\n routes: Array<{\n path: string;\n element_names?: string[];\n elementNames?: string[];\n }>;\n }>;\n return normalized.map((r) => ({\n moduleScope: r.moduleScope ?? r.module_scope ?? null,\n routes: r.routes.map((route) => ({\n path: route.path,\n elementNames: route.elementNames ?? route.element_names ?? [],\n })),\n }));\n }\n\n /**\n * Initialize the primary 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 * Register a named module for multi-module apps.\n *\n * Unlike setModule which sets the primary module, this registers an\n * additional module whose state is scoped to `module <name> { ... }`\n * blocks in the DSL.\n */\n registerModule(\n name: string,\n actions: string[],\n stateKeys: string[],\n initialState: Record<string, any>,\n ): void {\n const engine = this.ensureInitialized();\n engine.registerModule(\n name,\n actions,\n stateKeys,\n this.unwrapForWasm(initialState),\n );\n }\n\n /**\n * Get the current revision number.\n *\n * Note: the underlying WASM builder returns `bigint` in some targets\n * and `number` in others; this normalizes to `number` for consumer\n * ergonomics (revision counts don't exceed 2^53).\n */\n getRevision(): number {\n const engine = this.ensureInitialized();\n return Number(engine.getRevision());\n }\n\n /**\n * Clear resolved components and caches, preserving primitives and resolver.\n * Call before renderSource() during hot-reload so components are re-resolved\n * from fresh source files.\n */\n clearResolvedComponents(): void {\n const engine = this.ensureInitialized();\n engine.clearResolvedComponents();\n }\n\n /**\n * Clear the engine tree.\n */\n clearTree(): void {\n const engine = this.ensureInitialized();\n engine.clearTree();\n }\n\n /**\n * Full reset: clears tree, module, component registry, dependencies,\n * and revision. Render callback and component resolver are preserved.\n */\n reset(): void {\n const engine = this.ensureInitialized();\n engine.reset();\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 // ── Data Source Context ────────────────────────────────────────\n\n /**\n * Set (or replace) a named data source context.\n *\n * Registers the provider in the dependency graph, stores the data,\n * and re-renders every node bound to `$name.*`.\n *\n * @param name - Provider name (e.g., \"spacetime\", \"firebase\")\n * @param data - Full state object for this provider\n */\n setContext(name: string, data: Record<string, unknown>): void {\n const engine = this.ensureInitialized();\n try {\n engine.setContext(name, this.unwrapForWasm(data));\n } catch (err) {\n throw classifyEngineError(err);\n }\n log.debug(`Data source \"${name}\" context set`);\n }\n\n /**\n * Remove a data source context entirely.\n * Drops the provider's state and re-renders bound nodes (they resolve to null).\n */\n removeContext(name: string): void {\n const engine = this.ensureInitialized();\n engine.removeContext(name);\n }\n\n // ── Resource System ─────────────────────────────────────────────────\n\n /**\n * Register resources (name → raw SVG string) with the engine.\n *\n * Each SVG is parsed by the WASM engine. When the engine encounters\n * `Icon(@resources.heart)` in the DSL, it resolves the name from registered\n * resources and injects SVG path data into the Create patch props.\n *\n * @param map - Flat map of resource name to raw SVG string\n */\n registerResources(map: Record<string, string>): void {\n const engine = this.ensureInitialized();\n engine.registerResources(map);\n log.debug(`Resources registered (${Object.keys(map).length} entries)`);\n }\n}\n"
|
|
8
6
|
],
|
|
9
|
-
"mappings": "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",
|
|
10
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "0B860F9754DCCD3064756E2164756E21",
|
|
11
9
|
"names": []
|
|
12
10
|
}
|
package/dist/events.js
CHANGED
|
@@ -1,290 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, {
|
|
9
|
-
get: all[name],
|
|
10
|
-
enumerable: true,
|
|
11
|
-
configurable: true,
|
|
12
|
-
set: __exportSetter.bind(all, name)
|
|
13
|
-
});
|
|
14
|
-
};
|
|
15
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
16
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
17
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
18
|
-
}) : x)(function(x) {
|
|
19
|
-
if (typeof require !== "undefined")
|
|
20
|
-
return require.apply(this, arguments);
|
|
21
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// src/logger.ts
|
|
25
|
-
var LOG_LEVEL_ORDER = {
|
|
26
|
-
debug: 0,
|
|
27
|
-
info: 1,
|
|
28
|
-
warn: 2,
|
|
29
|
-
error: 3,
|
|
30
|
-
none: 4
|
|
31
|
-
};
|
|
32
|
-
var LOG_LEVEL_COLORS = {
|
|
33
|
-
debug: "\x1B[36m",
|
|
34
|
-
info: "\x1B[32m",
|
|
35
|
-
warn: "\x1B[33m",
|
|
36
|
-
error: "\x1B[31m"
|
|
37
|
-
};
|
|
38
|
-
var RESET_COLOR = "\x1B[0m";
|
|
39
|
-
function isProduction() {
|
|
40
|
-
if (typeof process !== "undefined" && process.env) {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
var config = {
|
|
46
|
-
level: isProduction() ? "error" : "info",
|
|
47
|
-
colors: true,
|
|
48
|
-
timestamps: false
|
|
49
|
-
};
|
|
50
|
-
function setLogLevel(level) {
|
|
51
|
-
config.level = level;
|
|
52
|
-
}
|
|
53
|
-
function getLogLevel() {
|
|
54
|
-
return config.level;
|
|
55
|
-
}
|
|
56
|
-
function configureLogger(options) {
|
|
57
|
-
config = { ...config, ...options };
|
|
58
|
-
}
|
|
59
|
-
function enableLogging() {
|
|
60
|
-
config.level = "debug";
|
|
61
|
-
}
|
|
62
|
-
function disableLogging() {
|
|
63
|
-
config.level = "none";
|
|
64
|
-
}
|
|
65
|
-
function setDebugMode(enabled) {
|
|
66
|
-
config.level = enabled ? "debug" : "error";
|
|
67
|
-
}
|
|
68
|
-
function isDebugMode() {
|
|
69
|
-
return config.level === "debug";
|
|
70
|
-
}
|
|
71
|
-
function shouldLog(level) {
|
|
72
|
-
return LOG_LEVEL_ORDER[level] >= LOG_LEVEL_ORDER[config.level];
|
|
73
|
-
}
|
|
74
|
-
function formatTag(tag, level) {
|
|
75
|
-
const timestamp = config.timestamps ? `${new Date().toISOString()} ` : "";
|
|
76
|
-
if (config.colors && level !== "none") {
|
|
77
|
-
const color = LOG_LEVEL_COLORS[level];
|
|
78
|
-
return `${timestamp}${color}[${tag}]${RESET_COLOR}`;
|
|
79
|
-
}
|
|
80
|
-
return `${timestamp}[${tag}]`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
class Logger {
|
|
84
|
-
tag;
|
|
85
|
-
constructor(tag) {
|
|
86
|
-
this.tag = tag;
|
|
87
|
-
}
|
|
88
|
-
debug(...args) {
|
|
89
|
-
if (!shouldLog("debug"))
|
|
90
|
-
return;
|
|
91
|
-
if (config.handler) {
|
|
92
|
-
config.handler.debug(this.tag, ...args);
|
|
93
|
-
} else {
|
|
94
|
-
console.log(formatTag(this.tag, "debug"), ...args);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
info(...args) {
|
|
98
|
-
if (!shouldLog("info"))
|
|
99
|
-
return;
|
|
100
|
-
if (config.handler) {
|
|
101
|
-
config.handler.info(this.tag, ...args);
|
|
102
|
-
} else {
|
|
103
|
-
console.info(formatTag(this.tag, "info"), ...args);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
warn(...args) {
|
|
107
|
-
if (!shouldLog("warn"))
|
|
108
|
-
return;
|
|
109
|
-
if (config.handler) {
|
|
110
|
-
config.handler.warn(this.tag, ...args);
|
|
111
|
-
} else {
|
|
112
|
-
console.warn(formatTag(this.tag, "warn"), ...args);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
error(...args) {
|
|
116
|
-
if (!shouldLog("error"))
|
|
117
|
-
return;
|
|
118
|
-
if (config.handler) {
|
|
119
|
-
config.handler.error(this.tag, ...args);
|
|
120
|
-
} else {
|
|
121
|
-
console.error(formatTag(this.tag, "error"), ...args);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
time(label, fn) {
|
|
125
|
-
if (!shouldLog("debug")) {
|
|
126
|
-
return fn();
|
|
127
|
-
}
|
|
128
|
-
const start = performance.now();
|
|
129
|
-
try {
|
|
130
|
-
return fn();
|
|
131
|
-
} finally {
|
|
132
|
-
const duration = performance.now() - start;
|
|
133
|
-
this.debug(`${label}: ${duration.toFixed(2)}ms`);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
async timeAsync(label, fn) {
|
|
137
|
-
if (!shouldLog("debug")) {
|
|
138
|
-
return fn();
|
|
139
|
-
}
|
|
140
|
-
const start = performance.now();
|
|
141
|
-
try {
|
|
142
|
-
return await fn();
|
|
143
|
-
} finally {
|
|
144
|
-
const duration = performance.now() - start;
|
|
145
|
-
this.debug(`${label}: ${duration.toFixed(2)}ms`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
child(subTag) {
|
|
149
|
-
return new Logger(`${this.tag}:${subTag}`);
|
|
150
|
-
}
|
|
151
|
-
debugIf(condition, ...args) {
|
|
152
|
-
if (condition)
|
|
153
|
-
this.debug(...args);
|
|
154
|
-
}
|
|
155
|
-
warnIf(condition, ...args) {
|
|
156
|
-
if (condition)
|
|
157
|
-
this.warn(...args);
|
|
158
|
-
}
|
|
159
|
-
errorIf(condition, ...args) {
|
|
160
|
-
if (condition)
|
|
161
|
-
this.error(...args);
|
|
162
|
-
}
|
|
163
|
-
loggedOnce = new Set;
|
|
164
|
-
warnOnce(key, ...args) {
|
|
165
|
-
if (this.loggedOnce.has(key))
|
|
166
|
-
return;
|
|
167
|
-
this.loggedOnce.add(key);
|
|
168
|
-
this.warn(...args);
|
|
169
|
-
}
|
|
170
|
-
debugOnce(key, ...args) {
|
|
171
|
-
if (this.loggedOnce.has(key))
|
|
172
|
-
return;
|
|
173
|
-
this.loggedOnce.add(key);
|
|
174
|
-
this.debug(...args);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
function createLogger(tag) {
|
|
178
|
-
return new Logger(tag);
|
|
179
|
-
}
|
|
180
|
-
var logger = createLogger("Hypen");
|
|
181
|
-
var log = {
|
|
182
|
-
debug: (tag, ...args) => {
|
|
183
|
-
if (!shouldLog("debug"))
|
|
184
|
-
return;
|
|
185
|
-
console.log(formatTag(tag, "debug"), ...args);
|
|
186
|
-
},
|
|
187
|
-
info: (tag, ...args) => {
|
|
188
|
-
if (!shouldLog("info"))
|
|
189
|
-
return;
|
|
190
|
-
console.info(formatTag(tag, "info"), ...args);
|
|
191
|
-
},
|
|
192
|
-
warn: (tag, ...args) => {
|
|
193
|
-
if (!shouldLog("warn"))
|
|
194
|
-
return;
|
|
195
|
-
console.warn(formatTag(tag, "warn"), ...args);
|
|
196
|
-
},
|
|
197
|
-
error: (tag, ...args) => {
|
|
198
|
-
if (!shouldLog("error"))
|
|
199
|
-
return;
|
|
200
|
-
console.error(formatTag(tag, "error"), ...args);
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
var frameworkLoggers = {
|
|
204
|
-
hypen: createLogger("Hypen"),
|
|
205
|
-
engine: createLogger("Engine"),
|
|
206
|
-
router: createLogger("Router"),
|
|
207
|
-
state: createLogger("State"),
|
|
208
|
-
events: createLogger("Events"),
|
|
209
|
-
remote: createLogger("Remote"),
|
|
210
|
-
renderer: createLogger("Renderer"),
|
|
211
|
-
module: createLogger("Module"),
|
|
212
|
-
lifecycle: createLogger("Lifecycle"),
|
|
213
|
-
loader: createLogger("Loader"),
|
|
214
|
-
context: createLogger("Context"),
|
|
215
|
-
discovery: createLogger("Discovery"),
|
|
216
|
-
plugin: createLogger("Plugin"),
|
|
217
|
-
canvas: createLogger("Canvas"),
|
|
218
|
-
debug: createLogger("Debug")
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
// src/events.ts
|
|
222
|
-
var log2 = frameworkLoggers.events;
|
|
223
|
-
|
|
224
|
-
class TypedEventEmitter {
|
|
225
|
-
eventBus = new Map;
|
|
226
|
-
emit(event, payload) {
|
|
227
|
-
const handlers = this.eventBus.get(event);
|
|
228
|
-
if (!handlers || handlers.size === 0) {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
handlers.forEach((handler) => {
|
|
232
|
-
try {
|
|
233
|
-
handler(payload);
|
|
234
|
-
} catch (error) {
|
|
235
|
-
log2.error(`Error in event handler for "${String(event)}":`, error);
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
on(event, handler) {
|
|
240
|
-
if (!this.eventBus.has(event)) {
|
|
241
|
-
this.eventBus.set(event, new Set);
|
|
242
|
-
}
|
|
243
|
-
const handlers = this.eventBus.get(event);
|
|
244
|
-
handlers.add(handler);
|
|
245
|
-
return () => {
|
|
246
|
-
handlers.delete(handler);
|
|
247
|
-
if (handlers.size === 0) {
|
|
248
|
-
this.eventBus.delete(event);
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
once(event, handler) {
|
|
253
|
-
const wrappedHandler = (payload) => {
|
|
254
|
-
handler(payload);
|
|
255
|
-
unsubscribe();
|
|
256
|
-
};
|
|
257
|
-
const unsubscribe = this.on(event, wrappedHandler);
|
|
258
|
-
return unsubscribe;
|
|
259
|
-
}
|
|
260
|
-
off(event, handler) {
|
|
261
|
-
const handlers = this.eventBus.get(event);
|
|
262
|
-
if (handlers) {
|
|
263
|
-
handlers.delete(handler);
|
|
264
|
-
if (handlers.size === 0) {
|
|
265
|
-
this.eventBus.delete(event);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
removeAllListeners(event) {
|
|
270
|
-
this.eventBus.delete(event);
|
|
271
|
-
}
|
|
272
|
-
clearAll() {
|
|
273
|
-
this.eventBus.clear();
|
|
274
|
-
}
|
|
275
|
-
listenerCount(event) {
|
|
276
|
-
return this.eventBus.get(event)?.size ?? 0;
|
|
277
|
-
}
|
|
278
|
-
eventNames() {
|
|
279
|
-
return Array.from(this.eventBus.keys());
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
function createEventEmitter() {
|
|
283
|
-
return new TypedEventEmitter;
|
|
284
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
TypedEventEmitter,
|
|
3
|
+
createEventEmitter
|
|
4
|
+
} from "./chunk-k12cwfst.js";
|
|
5
|
+
import"./chunk-avchpwhf.js";
|
|
6
|
+
import"./chunk-5gtx3pza.js";
|
|
285
7
|
export {
|
|
286
8
|
createEventEmitter,
|
|
287
9
|
TypedEventEmitter
|
|
288
10
|
};
|
|
289
11
|
|
|
290
|
-
//# debugId=
|
|
12
|
+
//# debugId=B9818117E59FFEB864756E2164756E21
|
package/dist/events.js.map
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": [
|
|
3
|
+
"sources": [],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Configurable Debug Logger\n *\n * Provides environment-aware logging that can be disabled in production.\n * Supports log levels, tagged output, and performance timing.\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"none\";\n\nexport interface LoggerConfig {\n /** Minimum log level (default: \"debug\" in dev, \"error\" in prod) */\n level: LogLevel;\n /** Enable colored output (default: true) */\n colors: boolean;\n /** Include timestamps (default: false) */\n timestamps: boolean;\n /** Custom log handler (default: console) */\n handler?: LogHandler;\n}\n\nexport interface LogHandler {\n debug(tag: string, ...args: unknown[]): void;\n info(tag: string, ...args: unknown[]): void;\n warn(tag: string, ...args: unknown[]): void;\n error(tag: string, ...args: unknown[]): void;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst LOG_LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n none: 4,\n};\n\nconst LOG_LEVEL_COLORS: Record<Exclude<LogLevel, \"none\">, string> = {\n debug: \"\\x1b[36m\", // Cyan\n info: \"\\x1b[32m\", // Green\n warn: \"\\x1b[33m\", // Yellow\n error: \"\\x1b[31m\", // Red\n};\n\nconst RESET_COLOR = \"\\x1b[0m\";\n\n// ============================================================================\n// Global Configuration\n// ============================================================================\n\n/**\n * Detect if running in production environment\n */\nfunction isProduction(): boolean {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env.NODE_ENV === \"production\";\n }\n return false;\n}\n\n/**\n * Default configuration\n */\nlet config: LoggerConfig = {\n level: isProduction() ? \"error\" : \"info\",\n colors: true,\n timestamps: false,\n};\n\n// ============================================================================\n// Configuration API\n// ============================================================================\n\n/**\n * Set the global log level\n */\nexport function setLogLevel(level: LogLevel): void {\n config.level = level;\n}\n\n/**\n * Get the current log level\n */\nexport function getLogLevel(): LogLevel {\n return config.level;\n}\n\n/**\n * Configure the logger\n */\nexport function configureLogger(options: Partial<LoggerConfig>): void {\n config = { ...config, ...options };\n}\n\n/**\n * Enable all logging (sets level to \"debug\")\n */\nexport function enableLogging(): void {\n config.level = \"debug\";\n}\n\n/**\n * Disable all logging (sets level to \"none\")\n */\nexport function disableLogging(): void {\n config.level = \"none\";\n}\n\n/**\n * Enable debug mode - alias for enableLogging()\n * Call this at app startup to see all debug logs\n *\n * @example\n * ```typescript\n * import { setDebugMode } from \"@hypen-space/core\";\n * setDebugMode(true);\n * ```\n */\nexport function setDebugMode(enabled: boolean): void {\n config.level = enabled ? \"debug\" : \"error\";\n}\n\n/**\n * Check if debug mode is enabled\n */\nexport function isDebugMode(): boolean {\n return config.level === \"debug\";\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVEL_ORDER[level] >= LOG_LEVEL_ORDER[config.level];\n}\n\nfunction formatTag(tag: string, level: LogLevel): string {\n const timestamp = config.timestamps ? `${new Date().toISOString()} ` : \"\";\n\n if (config.colors && level !== \"none\") {\n const color = LOG_LEVEL_COLORS[level as Exclude<LogLevel, \"none\">];\n return `${timestamp}${color}[${tag}]${RESET_COLOR}`;\n }\n\n return `${timestamp}[${tag}]`;\n}\n\n// ============================================================================\n// Logger Class\n// ============================================================================\n\n/**\n * Tagged logger instance\n *\n * @example\n * ```typescript\n * const log = createLogger(\"MyComponent\");\n * log.debug(\"initialized with\", { props });\n * log.error(\"failed to load\", error);\n * ```\n */\nexport class Logger {\n private readonly tag: string;\n\n constructor(tag: string) {\n this.tag = tag;\n }\n\n debug(...args: unknown[]): void {\n if (!shouldLog(\"debug\")) return;\n\n if (config.handler) {\n config.handler.debug(this.tag, ...args);\n } else {\n console.log(formatTag(this.tag, \"debug\"), ...args);\n }\n }\n\n info(...args: unknown[]): void {\n if (!shouldLog(\"info\")) return;\n\n if (config.handler) {\n config.handler.info(this.tag, ...args);\n } else {\n console.info(formatTag(this.tag, \"info\"), ...args);\n }\n }\n\n warn(...args: unknown[]): void {\n if (!shouldLog(\"warn\")) return;\n\n if (config.handler) {\n config.handler.warn(this.tag, ...args);\n } else {\n console.warn(formatTag(this.tag, \"warn\"), ...args);\n }\n }\n\n error(...args: unknown[]): void {\n if (!shouldLog(\"error\")) return;\n\n if (config.handler) {\n config.handler.error(this.tag, ...args);\n } else {\n console.error(formatTag(this.tag, \"error\"), ...args);\n }\n }\n\n /**\n * Time a function execution\n */\n time<T>(label: string, fn: () => T): T {\n if (!shouldLog(\"debug\")) {\n return fn();\n }\n\n const start = performance.now();\n try {\n return fn();\n } finally {\n const duration = performance.now() - start;\n this.debug(`${label}: ${duration.toFixed(2)}ms`);\n }\n }\n\n /**\n * Time an async function execution\n */\n async timeAsync<T>(label: string, fn: () => Promise<T>): Promise<T> {\n if (!shouldLog(\"debug\")) {\n return fn();\n }\n\n const start = performance.now();\n try {\n return await fn();\n } finally {\n const duration = performance.now() - start;\n this.debug(`${label}: ${duration.toFixed(2)}ms`);\n }\n }\n\n /**\n * Create a child logger with additional context\n */\n child(subTag: string): Logger {\n return new Logger(`${this.tag}:${subTag}`);\n }\n\n /**\n * Conditionally log based on a condition\n */\n debugIf(condition: boolean, ...args: unknown[]): void {\n if (condition) this.debug(...args);\n }\n\n warnIf(condition: boolean, ...args: unknown[]): void {\n if (condition) this.warn(...args);\n }\n\n errorIf(condition: boolean, ...args: unknown[]): void {\n if (condition) this.error(...args);\n }\n\n /**\n * Log once (useful for deprecation warnings)\n */\n private loggedOnce = new Set<string>();\n\n warnOnce(key: string, ...args: unknown[]): void {\n if (this.loggedOnce.has(key)) return;\n this.loggedOnce.add(key);\n this.warn(...args);\n }\n\n debugOnce(key: string, ...args: unknown[]): void {\n if (this.loggedOnce.has(key)) return;\n this.loggedOnce.add(key);\n this.debug(...args);\n }\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a tagged logger\n *\n * @example\n * ```typescript\n * const log = createLogger(\"Router\");\n * log.info(\"navigating to\", path);\n * ```\n */\nexport function createLogger(tag: string): Logger {\n return new Logger(tag);\n}\n\n// ============================================================================\n// Default Logger Instance\n// ============================================================================\n\n/**\n * Default logger for general use\n */\nexport const logger = createLogger(\"Hypen\");\n\n// ============================================================================\n// Shorthand Functions (untagged)\n// ============================================================================\n\n/**\n * Shorthand logging functions for quick use\n * Prefer createLogger() for component-specific logging\n */\nexport const log = {\n debug: (tag: string, ...args: unknown[]): void => {\n if (!shouldLog(\"debug\")) return;\n console.log(formatTag(tag, \"debug\"), ...args);\n },\n\n info: (tag: string, ...args: unknown[]): void => {\n if (!shouldLog(\"info\")) return;\n console.info(formatTag(tag, \"info\"), ...args);\n },\n\n warn: (tag: string, ...args: unknown[]): void => {\n if (!shouldLog(\"warn\")) return;\n console.warn(formatTag(tag, \"warn\"), ...args);\n },\n\n error: (tag: string, ...args: unknown[]): void => {\n if (!shouldLog(\"error\")) return;\n console.error(formatTag(tag, \"error\"), ...args);\n },\n};\n\n// ============================================================================\n// Predefined Loggers for Framework Components\n// ============================================================================\n\nexport const frameworkLoggers = {\n hypen: createLogger(\"Hypen\"),\n engine: createLogger(\"Engine\"),\n router: createLogger(\"Router\"),\n state: createLogger(\"State\"),\n events: createLogger(\"Events\"),\n remote: createLogger(\"Remote\"),\n renderer: createLogger(\"Renderer\"),\n module: createLogger(\"Module\"),\n lifecycle: createLogger(\"Lifecycle\"),\n loader: createLogger(\"Loader\"),\n context: createLogger(\"Context\"),\n discovery: createLogger(\"Discovery\"),\n plugin: createLogger(\"Plugin\"),\n canvas: createLogger(\"Canvas\"),\n debug: createLogger(\"Debug\"),\n};\n",
|
|
6
|
-
"/**\n * Type-safe Event System\n *\n * Provides strongly-typed event emission and subscription with autocomplete support.\n */\n\nimport { frameworkLoggers } from \"./logger.js\";\n\nconst log = frameworkLoggers.events;\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 log.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"
|
|
7
5
|
],
|
|
8
|
-
"mappings": "
|
|
9
|
-
"debugId": "
|
|
6
|
+
"mappings": "",
|
|
7
|
+
"debugId": "B9818117E59FFEB864756E2164756E21",
|
|
10
8
|
"names": []
|
|
11
9
|
}
|
package/dist/hypen.js
CHANGED
|
@@ -1,73 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
__defProp(target, name, {
|
|
9
|
-
get: all[name],
|
|
10
|
-
enumerable: true,
|
|
11
|
-
configurable: true,
|
|
12
|
-
set: __exportSetter.bind(all, name)
|
|
13
|
-
});
|
|
14
|
-
};
|
|
15
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
16
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
17
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
18
|
-
}) : x)(function(x) {
|
|
19
|
-
if (typeof require !== "undefined")
|
|
20
|
-
return require.apply(this, arguments);
|
|
21
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// src/hypen.ts
|
|
25
|
-
function createBindingProxy(root) {
|
|
26
|
-
const handler = {
|
|
27
|
-
get(_, prop) {
|
|
28
|
-
if (prop === Symbol.toPrimitive || prop === "toString" || prop === "valueOf") {
|
|
29
|
-
return () => `@{${root}}`;
|
|
30
|
-
}
|
|
31
|
-
if (typeof prop === "symbol") {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
if (prop === "toJSON") {
|
|
35
|
-
return () => `@{${root}}`;
|
|
36
|
-
}
|
|
37
|
-
return createBindingProxy(`${root}.${prop}`);
|
|
38
|
-
},
|
|
39
|
-
has() {
|
|
40
|
-
return true;
|
|
41
|
-
},
|
|
42
|
-
ownKeys() {
|
|
43
|
-
return [];
|
|
44
|
-
},
|
|
45
|
-
getOwnPropertyDescriptor() {
|
|
46
|
-
return {
|
|
47
|
-
configurable: true,
|
|
48
|
-
enumerable: true
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
return new Proxy({}, handler);
|
|
53
|
-
}
|
|
54
|
-
var state = createBindingProxy("state");
|
|
55
|
-
var item = createBindingProxy("item");
|
|
56
|
-
var index = {
|
|
57
|
-
[Symbol.toPrimitive]: () => "@{index}",
|
|
58
|
-
toString: () => "@{index}",
|
|
59
|
-
valueOf: () => "@{index}",
|
|
60
|
-
toJSON: () => "@{index}"
|
|
61
|
-
};
|
|
62
|
-
function hypen(strings, ...expressions) {
|
|
63
|
-
let result = strings[0];
|
|
64
|
-
for (let i = 0;i < expressions.length; i++) {
|
|
65
|
-
const expr = expressions[i];
|
|
66
|
-
result += String(expr);
|
|
67
|
-
result += strings[i + 1];
|
|
68
|
-
}
|
|
69
|
-
return result.trim();
|
|
70
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
hypen,
|
|
3
|
+
index,
|
|
4
|
+
item,
|
|
5
|
+
state
|
|
6
|
+
} from "./chunk-wp2ebn2m.js";
|
|
7
|
+
import"./chunk-5gtx3pza.js";
|
|
71
8
|
export {
|
|
72
9
|
state,
|
|
73
10
|
item,
|
|
@@ -75,4 +12,4 @@ export {
|
|
|
75
12
|
hypen
|
|
76
13
|
};
|
|
77
14
|
|
|
78
|
-
//# debugId=
|
|
15
|
+
//# debugId=6A915CA3B6D045F864756E2164756E21
|
package/dist/hypen.js.map
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": [
|
|
3
|
+
"sources": [],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Hypen Tagged Template Literal\n *\n * Enables single-file components with inline UI templates.\n *\n * The `hypen` tagged template preserves @{state.x} and @{item.x} bindings\n * instead of interpolating them, allowing you to write:\n *\n * @example\n * ```typescript\n * import { app, hypen, state } from \"@hypen-space/core\";\n *\n * export default app\n * .defineState({ count: 0 })\n * .onAction(\"increment\", ({ state }) => {\n * state.count += 1;\n * })\n * .ui(hypen`\n * Column {\n * Text(\"Count: @{state.count}\")\n * Button { Text(\"+\") }\n * .onClick(\"@actions.increment\")\n * }\n * `);\n * ```\n */\n\n/**\n * Creates a proxy that captures property access as a binding path string.\n *\n * When used in a template literal, the proxy's toString() returns the\n * full binding expression (e.g., \"@{state.user.name}\"). This lets you\n * interpolate JS variables into hypen templates without losing type safety.\n *\n * @example\n * ```typescript\n * const state = createBindingProxy('state');\n * String(state.user.name) // Returns: \"@{state.user.name}\"\n * ```\n */\nfunction createBindingProxy(root: string): any {\n const handler: ProxyHandler<object> = {\n get(_, prop: string | symbol): any {\n // Handle Symbol.toPrimitive, toString, and valueOf for string conversion\n if (\n prop === Symbol.toPrimitive ||\n prop === \"toString\" ||\n prop === \"valueOf\"\n ) {\n return () => `@{${root}}`;\n }\n\n // Handle other Symbol properties (e.g., Symbol.toStringTag)\n if (typeof prop === \"symbol\") {\n return undefined;\n }\n\n // Handle JSON.stringify\n if (prop === \"toJSON\") {\n return () => `@{${root}}`;\n }\n\n // Chain to nested property: state.user -> state.user.name\n return createBindingProxy(`${root}.${prop}`);\n },\n\n // Support for `in` operator\n has() {\n return true;\n },\n\n // Support for Object.keys() - return empty to avoid enumeration issues\n ownKeys() {\n return [];\n },\n\n getOwnPropertyDescriptor() {\n return {\n configurable: true,\n enumerable: true,\n };\n },\n };\n\n return new Proxy({} as any, handler);\n}\n\n/**\n * Proxy for state bindings.\n *\n * In hypen templates, prefer the direct `@{state.x}` syntax. This proxy\n * exists for cases where you want to interpolate JS values into templates\n * — e.g., `hypen\\`Text(\"${state.user.name}\")\\`` produces the same string\n * as `hypen\\`Text(\"@{state.user.name}\")\\``.\n *\n * @example\n * ```typescript\n * // Preferred: direct syntax\n * hypen`Text(\"Hello, @{state.user.name}\")`\n *\n * // Also works: proxy interpolation\n * hypen`Text(\"Hello, ${state.user.name}\")`\n * ```\n */\nexport const state: any = createBindingProxy(\"state\");\n\n/**\n * Proxy for item bindings in list iteration.\n *\n * Use inside List components to reference the current item:\n *\n * @example\n * ```typescript\n * hypen`\n * List(@state.items) {\n * Text(\"@{item.name}: @{item.price}\")\n * }\n * `\n * ```\n */\nexport const item: any = createBindingProxy(\"item\");\n\n/**\n * Proxy for index in list iteration.\n *\n * Use inside List components to reference the current index:\n *\n * @example\n * ```typescript\n * hypen`\n * List(@state.items) {\n * Text(\"Item #@{index}: @{item.name}\")\n * }\n * `\n * ```\n */\nexport const index: any = {\n [Symbol.toPrimitive]: () => \"@{index}\",\n toString: () => \"@{index}\",\n valueOf: () => \"@{index}\",\n toJSON: () => \"@{index}\",\n};\n\n/**\n * Tagged template literal for Hypen DSL templates.\n *\n * Prefer the direct `@{state.x}` / `@{item.x}` syntax. The `state`, `item`,\n * and `index` proxies are available for interpolating JS variables or\n * mixing dynamic content with bindings.\n *\n * @example\n * ```typescript\n * import { hypen, state, item } from \"@hypen-space/core\";\n *\n * // Preferred: direct binding syntax\n * const t1 = hypen`Text(\"Count: @{state.count}\")`;\n *\n * // Nested paths work the same way\n * const t2 = hypen`Text(\"Hello, @{state.user.profile.name}\")`;\n *\n * // List with item binding\n * const t3 = hypen`\n * List(@state.products) {\n * Text(\"@{item.name} - $@{item.price}\")\n * }\n * `;\n *\n * // Interpolate JS variables alongside bindings\n * const title = \"My App\";\n * const t4 = hypen`Text(\"${title}: @{state.count}\")`;\n * // Result: 'Text(\"My App: @{state.count}\")'\n * ```\n *\n * @param strings - Template literal string parts\n * @param expressions - Interpolated JS values or binding proxies\n * @returns The template string with bindings preserved\n */\nexport function hypen(\n strings: TemplateStringsArray,\n ...expressions: unknown[]\n): string {\n let result = strings[0];\n\n for (let i = 0; i < expressions.length; i++) {\n const expr = expressions[i];\n\n // Convert expression to string\n // Binding proxies will return \"@{state.x}\" via their toString()\n result += String(expr);\n result += strings[i + 1]!;\n }\n\n return result!.trim();\n}\n\n/**\n * Type helper for defining state shape.\n * Use with state proxy for better IDE support in complex scenarios.\n *\n * @example\n * ```typescript\n * type MyState = { user: { name: string; age: number } };\n * const typedState = state as StateProxy<MyState>;\n * ```\n */\nexport type StateProxy<T> = {\n [K in keyof T]: T[K] extends object\n ? StateProxy<T[K]> & { toString(): string }\n : { toString(): string };\n} & { toString(): string };\n\n/**\n * Type helper for item proxy in lists.\n */\nexport type ItemProxy<T> = StateProxy<T>;\n"
|
|
6
5
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
6
|
+
"mappings": "",
|
|
7
|
+
"debugId": "6A915CA3B6D045F864756E2164756E21",
|
|
9
8
|
"names": []
|
|
10
9
|
}
|