@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
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": [
|
|
3
|
+
"sources": [],
|
|
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 * Data Source Plugin System for Hypen\n *\n * Enables live subscription databases (SpacetimeDB, Firebase, Convex, Electric SQL)\n * to push data into the Hypen reactive engine via a unified plugin interface.\n *\n * UI bindings use the `@provider.path` syntax:\n * - `@spacetime.messages` → SpacetimeDB messages table\n * - `@firebase.user.profile` → Firebase user profile\n * - `@convex.tasks` → Convex tasks table\n *\n * @module\n */\n\n// ---------------------------------------------------------------------------\n// Core Types\n// ---------------------------------------------------------------------------\n\n/** Connection status for a data source provider */\nexport type DataSourceStatus =\n | \"disconnected\"\n | \"connecting\"\n | \"connected\"\n | \"reconnecting\"\n | \"error\";\n\n/** Describes a subscription to a table or query */\nexport interface DataSourceQuery {\n /** Table or collection name (e.g., \"messages\", \"users\") */\n table: string;\n /** Optional filter criteria */\n filter?: Record<string, unknown>;\n /** Optional raw query string (e.g., SQL for SpacetimeDB) */\n sql?: string;\n}\n\n/** Handle returned by subscribe() — call unsubscribe() to stop receiving updates */\nexport interface DataSourceSubscription {\n /** Stop receiving updates for this subscription */\n unsubscribe(): void;\n /** Current subscription status */\n status: \"pending\" | \"applied\" | \"error\";\n /** Error details if status is \"error\" */\n error?: Error;\n}\n\n/** Describes a batch of changes pushed by a plugin */\nexport interface DataSourceChange {\n /** Changed paths relative to the provider root (e.g., [\"messages\", \"users\"]) */\n paths: string[];\n /** New values at those paths */\n values: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin Interface\n// ---------------------------------------------------------------------------\n\n/**\n * Interface that all data source plugins must implement.\n *\n * A plugin manages the connection lifecycle and translates database-specific\n * events (row inserts, updates, deletes) into `DataSourceChange` objects that\n * the Hypen engine can consume.\n *\n * @typeParam TConfig - Plugin-specific configuration type\n *\n * @example\n * ```typescript\n * class SpacetimeDBPlugin implements DataSourcePlugin<SpacetimeDBConfig> {\n * readonly name = \"spacetime\";\n * status: DataSourceStatus = \"disconnected\";\n *\n * async connect(config: SpacetimeDBConfig, onChange: (change: DataSourceChange) => void) {\n * // Connect to SpacetimeDB, subscribe to tables, push changes via onChange\n * }\n * // ...\n * }\n * ```\n */\nexport interface DataSourcePlugin<TConfig = unknown> {\n /** Unique provider name (e.g., \"spacetime\", \"firebase\", \"convex\") */\n readonly name: string;\n\n /** Current connection status */\n status: DataSourceStatus;\n\n /**\n * Connect to the data source and begin pushing changes.\n *\n * @param config - Plugin-specific configuration\n * @param onChange - Callback to push data changes into the engine.\n * The plugin MUST call this whenever subscribed data changes.\n */\n connect(config: TConfig, onChange: (change: DataSourceChange) => void): Promise<void>;\n\n /**\n * Subscribe to a specific table or query.\n * Returns a handle to unsubscribe later.\n */\n subscribe(query: DataSourceQuery): DataSourceSubscription;\n\n /**\n * Call a remote procedure / reducer / mutation.\n *\n * @param method - Method name (e.g., \"sendMessage\" for SpacetimeDB reducer)\n * @param args - Arguments to pass\n * @returns The result from the remote call\n */\n call(method: string, ...args: unknown[]): Promise<unknown>;\n\n /**\n * Disconnect from the data source and clean up all subscriptions.\n */\n disconnect(): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// Data Source Manager\n// ---------------------------------------------------------------------------\n\n/** Interface for the engine's data source operations (maps to WASM setContext/removeContext) */\nexport interface IDataSourceEngine {\n /**\n * Set (or replace) a named data source context.\n * Registers the provider, stores the data, and re-renders bound nodes.\n * Sparse merging should happen at the SDK layer before calling this.\n */\n setContext(name: string, data: Record<string, unknown>): void;\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}\n\n/**\n * Manages data source plugin lifecycles and bridges them to the Hypen engine.\n *\n * The manager:\n * 1. Registers plugins with the engine (creates state slots)\n * 2. Connects plugins and wires their onChange callbacks to engine updates\n * 3. Manages subscription lifecycles\n * 4. Handles cleanup on disconnect\n *\n * @example\n * ```typescript\n * const manager = new DataSourceManager(engine);\n *\n * // Register and connect a SpacetimeDB plugin\n * await manager.use(new SpacetimeDBPlugin(), {\n * uri: \"ws://localhost:3000\",\n * moduleName: \"chat\",\n * tables: [\"user\", \"message\"],\n * });\n *\n * // Access plugin for mutations\n * await manager.get(\"spacetime\").call(\"sendMessage\", \"Hello!\");\n *\n * // Clean up\n * await manager.disconnectAll();\n * ```\n */\nexport class DataSourceManager {\n private plugins = new Map<string, DataSourcePlugin>();\n private configs = new Map<string, unknown>();\n /** Accumulated state per provider — sparse merging happens here before setContext */\n private state = new Map<string, Record<string, unknown>>();\n private engine: IDataSourceEngine;\n\n constructor(engine: IDataSourceEngine) {\n this.engine = engine;\n }\n\n /**\n * Register, connect, and start a data source plugin.\n *\n * @param plugin - The plugin instance\n * @param config - Plugin-specific configuration\n */\n async use<C>(plugin: DataSourcePlugin<C>, config: C): Promise<void> {\n const { name } = plugin;\n\n // Initialize state slot\n this.state.set(name, {});\n\n // Store references\n this.plugins.set(name, plugin as DataSourcePlugin);\n this.configs.set(name, config);\n\n // Connect the plugin with an onChange callback that merges sparse data\n // and pushes the full state via setContext\n await plugin.connect(config, (change: DataSourceChange) => {\n // Merge changed paths into the accumulated state\n const current = this.state.get(name) ?? {};\n for (const path of change.paths) {\n if (path in change.values) {\n current[path] = change.values[path];\n }\n }\n this.state.set(name, current);\n\n // Push the full merged state to the engine\n this.engine.setContext(name, current);\n });\n }\n\n /**\n * Get a registered plugin by name.\n * Useful for calling mutations: `manager.get(\"spacetime\").call(\"sendMessage\", text)`\n */\n get<T extends DataSourcePlugin = DataSourcePlugin>(name: string): T | undefined {\n return this.plugins.get(name) as T | undefined;\n }\n\n /** Check if a plugin is registered */\n has(name: string): boolean {\n return this.plugins.has(name);\n }\n\n /** Get all registered provider names */\n getNames(): string[] {\n return Array.from(this.plugins.keys());\n }\n\n /** Get the status of a specific plugin */\n getStatus(name: string): DataSourceStatus | undefined {\n return this.plugins.get(name)?.status;\n }\n\n /**\n * Disconnect and remove a specific plugin.\n */\n async remove(name: string): Promise<void> {\n const plugin = this.plugins.get(name);\n if (plugin) {\n await plugin.disconnect();\n this.plugins.delete(name);\n this.configs.delete(name);\n this.state.delete(name);\n this.engine.removeContext(name);\n }\n }\n\n /**\n * Disconnect all plugins and clean up.\n */\n async disconnectAll(): Promise<void> {\n const names = Array.from(this.plugins.keys());\n await Promise.all(names.map((name) => this.remove(name)));\n }\n}\n",
|
|
7
|
-
"/**\n * Portable helper DI seam for `@hypen-space/core`.\n *\n * `@hypen-space/core` is WASM-free: it ships to contexts (tree-shakers,\n * browser remote-client bundles) that must not pull in the 2 MB engine\n * binary. But every Hypen runtime — Node via `@hypen-space/server`,\n * browser SPA via `@hypen-space/web-engine`, tests via the bun preload\n * — composes core with a host that HAS loaded the engine. Those\n * packages call [`setPortableImpl`] at their init time, plugging the\n * canonical Rust-engine impls (`hypen-engine-rs/src/portable/`) into\n * core.\n *\n * There is no TypeScript fallback. A core instance whose portable\n * helpers are called before `setPortableImpl` has run throws a clear\n * error pointing at the fix. Reasons:\n *\n * * Any fallback is a second implementation to maintain, exactly the\n * drift tax this whole refactor eliminated for the other four SDKs.\n * * Core's own consumers of the portable helpers (`HypenRouter.matchPath`,\n * `createObservableState`'s `notifyChange`) are never reached in\n * remote-client-only browser bundles — those bundles drive UI purely\n * from server-pushed patches.\n * * Callers who DO reach the helpers (server, web-engine, tests) always\n * have an engine available.\n */\n\nimport type { StateChange, StatePath } from \"./state\";\n\nexport interface PortableImpl {\n diffState(oldState: any, newState: any, basePath?: string): StateChange;\n matchPath(\n pattern: string,\n path: string,\n ): { params: Record<string, string> } | null;\n pathGet(value: any, path: string): unknown;\n pathHas(value: any, path: string): boolean;\n pathSet(value: any, path: string, newValue: any): any;\n pathDelete(value: any, path: string): { value: any; removed: boolean };\n encodeUriComponent(input: string): string;\n decodeUriComponent(input: string): string;\n parseQuery(fullPath: string): { path: string; query: Record<string, string> };\n buildUrl(path: string, query: Record<string, string>): string;\n}\n\nfunction notInstalled(name: string): never {\n throw new Error(\n `[@hypen-space/core] Portable helper \"${name}\" called before the engine was installed. ` +\n `Import @hypen-space/server, @hypen-space/web-engine, or call setPortableImpl() before use.`,\n );\n}\n\nlet current: PortableImpl = {\n diffState: () => notInstalled(\"diffState\"),\n matchPath: () => notInstalled(\"matchPath\"),\n pathGet: () => notInstalled(\"pathGet\"),\n pathHas: () => notInstalled(\"pathHas\"),\n pathSet: () => notInstalled(\"pathSet\"),\n pathDelete: () => notInstalled(\"pathDelete\"),\n encodeUriComponent: () => notInstalled(\"encodeUriComponent\"),\n decodeUriComponent: () => notInstalled(\"decodeUriComponent\"),\n parseQuery: () => notInstalled(\"parseQuery\"),\n buildUrl: () => notInstalled(\"buildUrl\"),\n};\n\n/**\n * Install the engine-backed [`PortableImpl`]. Called once by\n * `@hypen-space/server` at import time (synchronous wasm-node load) or\n * by `@hypen-space/web-engine` inside `Engine.init()` once the browser\n * wasm module resolves.\n *\n * Passing `null` resets to the \"not installed\" throwing default — used\n * by test teardown when you want to verify the no-engine error path.\n */\nexport function setPortableImpl(impl: PortableImpl | null): void {\n if (impl === null) {\n current = {\n diffState: () => notInstalled(\"diffState\"),\n matchPath: () => notInstalled(\"matchPath\"),\n pathGet: () => notInstalled(\"pathGet\"),\n pathHas: () => notInstalled(\"pathHas\"),\n pathSet: () => notInstalled(\"pathSet\"),\n pathDelete: () => notInstalled(\"pathDelete\"),\n encodeUriComponent: () => notInstalled(\"encodeUriComponent\"),\n decodeUriComponent: () => notInstalled(\"decodeUriComponent\"),\n parseQuery: () => notInstalled(\"parseQuery\"),\n buildUrl: () => notInstalled(\"buildUrl\"),\n };\n return;\n }\n current = impl;\n}\n\n/**\n * Live portable API. Every call dispatches to whatever\n * [`setPortableImpl`] most recently installed.\n */\nexport const portable: PortableImpl = {\n diffState: (o, n, b) => current.diffState(o, n, b),\n matchPath: (p, path) => current.matchPath(p, path),\n pathGet: (v, p) => current.pathGet(v, p),\n pathHas: (v, p) => current.pathHas(v, p),\n pathSet: (v, p, nv) => current.pathSet(v, p, nv),\n pathDelete: (v, p) => current.pathDelete(v, p),\n encodeUriComponent: (s) => current.encodeUriComponent(s),\n decodeUriComponent: (s) => current.decodeUriComponent(s),\n parseQuery: (f) => current.parseQuery(f),\n buildUrl: (p, q) => current.buildUrl(p, q),\n};\n\n// `StatePath` is still part of this module's public surface via\n// re-export; keeping it reachable from `@hypen-space/core/portable`\n// simplifies bindings in server / web-engine adapters.\nexport type { StatePath } from \"./state\";\n",
|
|
8
|
-
"/**\n * State management with observer pattern and diffing\n *\n * Uses a proxy-based approach with self-detection to avoid\n * creating nested proxies repeatedly.\n */\n\nimport { portable } from \"./portable\";\n\n// Symbol for proxy detection (more robust than string property)\nconst IS_PROXY = Symbol.for('hypen.isProxy');\nconst RAW_TARGET = Symbol.for('hypen.rawTarget');\n\nexport type StatePath = string; // e.g., \"user.name\", \"items.0.title\"\n\n/**\n * Represents a change in state with full path information\n */\nexport interface StateChange {\n paths: StatePath[];\n newValues: Record<StatePath, any>;\n}\n\n/**\n * Options for state observer\n */\nexport interface StateObserverOptions {\n onChange: (change: StateChange) => void;\n pathPrefix?: string; // For nested observers\n}\n\n/**\n * Deep clone an object, using structuredClone when available.\n * Handles proxy objects, circular references, and special types.\n */\nfunction deepClone<T>(obj: T): T {\n // Handle primitives and null\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n // Handle functions (pass through, can't be cloned)\n if (typeof obj === 'function') {\n return obj;\n }\n\n // Handle proxy objects with snapshot method\n if (typeof (obj as any).__getSnapshot === 'function') {\n return (obj as any).__getSnapshot() as T;\n }\n\n // Handle types that can't be cloned (return as-is)\n if (obj instanceof WeakMap || obj instanceof WeakSet) {\n return obj;\n }\n\n // Use a WeakMap to track visited objects and handle circular references\n const visited = new WeakMap();\n\n function cloneInternal(value: any): any {\n if (value === null || typeof value !== 'object') {\n return value;\n }\n\n // Functions can't be cloned, pass through\n if (typeof value === 'function') {\n return value;\n }\n\n // Check for circular reference\n if (visited.has(value)) {\n return visited.get(value);\n }\n\n // Handle types that can't be cloned\n if (value instanceof WeakMap || value instanceof WeakSet) {\n return value;\n }\n\n // Try structuredClone for supported types (Date, Map, Set, etc.)\n // This is faster than manual cloning for these types\n if (\n value instanceof Date ||\n value instanceof RegExp ||\n value instanceof Map ||\n value instanceof Set ||\n ArrayBuffer.isView(value) ||\n value instanceof ArrayBuffer\n ) {\n try {\n return structuredClone(value);\n } catch {\n // If structuredClone fails, fall through to manual handling\n }\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n const arrClone: any[] = [];\n visited.set(value, arrClone);\n for (let i = 0; i < value.length; i++) {\n arrClone[i] = cloneInternal(value[i]);\n }\n return arrClone;\n }\n\n // Handle plain objects\n const objClone: any = {};\n visited.set(value, objClone);\n\n // Clone string keys\n for (const key in value) {\n if (Object.prototype.hasOwnProperty.call(value, key)) {\n objClone[key] = cloneInternal(value[key]);\n }\n }\n\n // Clone Symbol keys\n const symbolKeys = Object.getOwnPropertySymbols(value);\n for (const sym of symbolKeys) {\n objClone[sym] = cloneInternal(value[sym]);\n }\n\n return objClone;\n }\n\n return cloneInternal(obj);\n}\n\n/**\n * Compare two values and detect changes with full paths.\n *\n * Thin wrapper over [`portable.diffState`] — the algorithm lives in\n * the Rust engine at `hypen-engine-rs/src/portable/diff.rs` and is\n * called through the WASM installed by `@hypen-space/server` /\n * `@hypen-space/web-engine`. When `@hypen-space/core` is used\n * standalone (no WASM available), a byte-identical TS fallback in\n * `portable.ts` takes over.\n */\nfunction diffState(\n oldState: any,\n newState: any,\n basePath: string = \"\"\n): StateChange {\n return portable.diffState(oldState, newState, basePath);\n}\n\n/**\n * Create an observable state object that tracks changes\n */\nexport function createObservableState<T extends object>(\n initialState: T,\n options?: StateObserverOptions\n): T {\n // Use default options if not provided\n const opts: StateObserverOptions = options || { onChange: () => {} };\n\n // Handle null/undefined by using an empty object\n // This allows modules to start with null state\n if (initialState === null || initialState === undefined) {\n initialState = {} as T;\n }\n\n // Detect and reject primitive wrapper objects (Number, String, Boolean)\n // These cannot be properly proxied due to internal slots\n if (\n initialState instanceof Number ||\n initialState instanceof String ||\n initialState instanceof Boolean\n ) {\n throw new TypeError(\n \"Cannot create observable state from primitive wrapper objects (Number, String, Boolean). \" +\n \"Use plain primitives or regular objects instead.\"\n );\n }\n\n // Clone the initial state to ensure each observable has its own copy\n // This prevents multiple modules from sharing the same underlying state object\n initialState = deepClone(initialState);\n\n // Keep a snapshot of the last known state\n let lastSnapshot = deepClone(initialState);\n const pathPrefix = opts.pathPrefix || \"\";\n\n // Track if we're in a batch update\n let batchDepth = 0;\n let pendingChange: StateChange | null = null;\n\n function notifyChange() {\n if (batchDepth > 0) return;\n\n // Compare current state with last snapshot\n const change = diffState(lastSnapshot, state, pathPrefix);\n\n if (change.paths.length > 0) {\n // Update snapshot\n lastSnapshot = deepClone(state);\n\n // Merge with pending changes if any\n if (pendingChange) {\n change.paths.push(...pendingChange.paths);\n Object.assign(change.newValues, pendingChange.newValues);\n pendingChange = null;\n }\n\n // Notify\n opts.onChange(change);\n }\n }\n\n // Track if we have a pending microtask notification\n let notificationPending = false;\n\n function scheduleBatch() {\n if (batchDepth === 0) {\n // If not in a batch, schedule notification in next microtask to coalesce rapid changes\n if (!notificationPending) {\n notificationPending = true;\n queueMicrotask(() => {\n notificationPending = false;\n if (batchDepth === 0) {\n notifyChange();\n } else {\n // A batch started after we scheduled; the batch's __endBatch will\n // call notifyChange() when it completes, so nothing to do here.\n }\n });\n }\n } else {\n // Inside a batch — mark that changes occurred so __endBatch knows to notify\n pendingChange = pendingChange || { paths: [], newValues: {} };\n }\n }\n\n // WeakMap to cache proxies by their raw target\n // This is essential for circular reference handling\n const proxyCache = new WeakMap<object, any>();\n\n function createProxy(target: any, basePath: string): any {\n // Check cache first (handles circular references)\n const cached = proxyCache.get(target);\n if (cached) return cached;\n\n const proxy = new Proxy(target, {\n get(obj, prop) {\n // Self-detection: if checking IS_PROXY, return true\n // This allows us to detect if a value is already proxied\n if (prop === IS_PROXY) return true;\n\n // Allow access to raw target (useful for debugging/serialization)\n if (prop === RAW_TARGET) return obj;\n\n // Expose batch control methods\n if (prop === \"__beginBatch\") {\n return () => {\n batchDepth++;\n };\n }\n if (prop === \"__endBatch\") {\n return () => {\n batchDepth--;\n if (batchDepth === 0) {\n notifyChange();\n }\n };\n }\n if (prop === \"__getSnapshot\") {\n return () => deepClone(obj);\n }\n\n const value = obj[prop];\n\n // Return proxied nested objects/arrays, but NOT special types\n if (value && typeof value === \"object\") {\n // Fast path: if already a proxy, return as-is\n // This check is O(1) and avoids WeakMap lookup\n if ((value as any)[IS_PROXY]) {\n return value;\n }\n\n // Check for special object types that should not be proxied\n if (\n value instanceof Date ||\n value instanceof RegExp ||\n value instanceof Map ||\n value instanceof Set ||\n value instanceof WeakMap ||\n value instanceof WeakSet\n ) {\n return value;\n }\n\n // Check cache for this value (handles circular refs and repeated access)\n const cachedNested = proxyCache.get(value);\n if (cachedNested) {\n return cachedNested;\n }\n\n // Create proxy for nested object/array\n const nestedProxy = createProxy(value, basePath ? `${basePath}.${String(prop)}` : String(prop));\n return nestedProxy;\n }\n\n return value;\n },\n\n set(obj, prop, value) {\n const oldValue = obj[prop];\n\n // If setting an object that's already a proxy, unwrap it first\n // to store the raw value (prevents proxy-wrapping-proxy)\n if (value && typeof value === \"object\" && (value as any)[IS_PROXY]) {\n value = (value as any)[RAW_TARGET];\n }\n\n // Set the new value\n obj[prop] = value;\n\n if (oldValue !== value) {\n scheduleBatch();\n }\n\n return true;\n },\n\n deleteProperty(obj, prop) {\n const existed = Object.prototype.hasOwnProperty.call(obj, prop);\n const result = delete obj[prop];\n if (existed) {\n scheduleBatch();\n }\n return result;\n },\n });\n\n // Cache the proxy before returning\n proxyCache.set(target, proxy);\n return proxy;\n }\n\n const state = createProxy(initialState, pathPrefix);\n return state as T;\n}\n\n/**\n * Helper to batch multiple state updates\n */\nexport function batchStateUpdates<T>(state: T, fn: () => void): void {\n const s = state as any;\n if (s.__beginBatch && s.__endBatch) {\n s.__beginBatch();\n try {\n fn();\n } finally {\n s.__endBatch();\n }\n } else {\n fn();\n }\n}\n\n/**\n * Get a snapshot of the current state\n */\nexport function getStateSnapshot<T>(state: T): T {\n const s = state as any;\n if (s.__getSnapshot) {\n return s.__getSnapshot();\n }\n return deepClone(state);\n}\n\n/**\n * Check if a value is a Hypen state proxy\n */\nexport function isStateProxy(value: unknown): boolean {\n return value !== null && typeof value === 'object' && (value as any)[IS_PROXY] === true;\n}\n\n/**\n * Get the raw (unwrapped) target from a proxy\n * Returns the value as-is if not a proxy\n */\nexport function unwrapProxy<T>(value: T): T {\n if (value !== null && typeof value === 'object' && (value as any)[IS_PROXY]) {\n return (value as any)[RAW_TARGET];\n }\n return value;\n}\n",
|
|
9
|
-
"/**\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",
|
|
10
|
-
"/**\n * Hypen App Builder API\n * Implements the stateful module system from RFC-0001\n */\n\nimport type { Action } from \"./types.js\";\nimport type { Session } from \"./remote/types.js\";\nimport { type Result, Ok, Err, fromPromise, ActionError, HypenError } from \"./result.js\";\nimport { DataSourceManager, type DataSourcePlugin, type IDataSourceEngine } from \"./datasource.js\";\nimport type { StateStore } from \"./persistence.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 registerModule(name: string, actions: string[], stateKeys: string[], initialState: unknown): void;\n onAction(actionName: string, handler: (action: Action) => void | Promise<void>): void;\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 */\n updateStateSparse(\n scope: string | null,\n paths: string[],\n values: Record<string, unknown>\n ): void;\n}\n\nimport { createObservableState, type StateChange, getStateSnapshot } from \"./state.js\";\nimport type { HypenRouter } from \"./router.js\";\nimport type { HypenGlobalContext, ModuleReference } from \"./context.js\";\nimport { createLogger } from \"./logger.js\";\n\nconst log = createLogger(\"ModuleInstance\");\n\nexport type ActionContext<P = unknown> = {\n name: string;\n payload?: P;\n sender?: string;\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: HypenRouter | null;\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, P = unknown> {\n action: ActionContext<P>;\n state: T;\n context: GlobalContext;\n /** Access to registered data source plugins for mutations */\n dataSources: DataSourceAccessor;\n}\n\n/**\n * Provides typed access to registered data source plugins.\n * Unknown method calls are forwarded to `plugin.call()`:\n * `dataSources.spacetime.sendMessage(text)` → `plugin.call(\"sendMessage\", text)`\n *\n * You can also call `.call()` directly if you prefer:\n * `dataSources.spacetime.call(\"sendMessage\", text)`\n */\nexport interface DataSourceAccessor {\n [providerName: string]: DataSourcePlugin & Record<string, (...args: unknown[]) => Promise<unknown>>;\n}\n\n/**\n * Action handler - receives all context in a single object\n */\nexport type ActionHandler<T, P = unknown> = (ctx: ActionHandlerContext<T, P>) => void | Promise<void>;\n\n/**\n * Context passed to onDisconnect handler\n */\nexport interface DisconnectContext<T> {\n /** Current state snapshot (ready to serialize and save) */\n state: T;\n /** Session information */\n session: Session;\n}\n\n/**\n * Context passed to onReconnect handler\n */\nexport interface ReconnectContext<T> {\n /** Session information */\n session: Session;\n /** Call this with saved state to restore it */\n restore: (savedState: T) => void;\n}\n\n/**\n * Context passed to onExpire handler\n */\nexport interface ExpireContext {\n /** Session information */\n session: Session;\n}\n\n/**\n * Handler called when client disconnects (session still alive for TTL)\n */\nexport type DisconnectHandler<T> = (ctx: DisconnectContext<T>) => void | Promise<void>;\n\n/**\n * Handler called when client reconnects with existing session\n */\nexport type ReconnectHandler<T> = (ctx: ReconnectContext<T>) => void | Promise<void>;\n\n/**\n * Handler called when session TTL expires (client never reconnected)\n */\nexport type ExpireHandler = (ctx: ExpireContext) => void | Promise<void>;\n\n/**\n * Context passed to onError handler\n */\nexport interface ErrorContext<T> {\n /** The error that occurred */\n error: HypenError;\n /** Current state (for inspection, not mutation during error handling) */\n state: T;\n /** The action name if error occurred in an action handler */\n actionName?: string;\n /** The lifecycle phase if error occurred in a lifecycle handler */\n lifecycle?: \"created\" | \"activated\" | \"deactivated\" | \"destroyed\" | \"disconnect\" | \"reconnect\" | \"expire\";\n}\n\n/**\n * Error handler return type - controls error propagation\n */\nexport type ErrorHandlerResult =\n | void // Continue with default behavior (log + emit)\n | { handled: true } // Error was handled, skip default behavior\n | { retry: true } // Retry the operation (only for actions)\n | { rethrow: true }; // Re-throw the error\n\n/**\n * Handler called when an error occurs in the module\n */\nexport type ErrorHandler<T> = (ctx: ErrorContext<T>) => ErrorHandlerResult | Promise<ErrorHandlerResult>;\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 /**\n * Inline UI template for single-file components.\n * Set via the `.ui(hypen`...`)` method.\n */\n template?: string;\n /**\n * Data source plugins registered via `.useDataSource()`.\n * Each entry contains the plugin and its configuration.\n */\n dataSources?: Array<{ plugin: DataSourcePlugin; config: unknown }>;\n /**\n * Pluggable state store for persistence across sessions.\n * Set via the `.persist(store)` builder method.\n */\n stateStore?: StateStore<T>;\n handlers: {\n onCreated?: LifecycleHandler<T>;\n /**\n * Called every time the module becomes the active route target.\n * Runs after `onCreated` on first mount, and again on each re-mount\n * from the ManagedRouter's persistence cache. Use for data refresh,\n * subscription (re)connects, or any \"screen became visible\" work.\n */\n onActivated?: LifecycleHandler<T>;\n /**\n * Called every time the module stops being the active route target.\n * Runs before the module is cached for persistence OR before\n * `onDestroyed` if the module is being torn down. Use for pausing\n * timers, tearing down ephemeral subscriptions, etc.\n */\n onDeactivated?: LifecycleHandler<T>;\n onAction: Map<string, ActionHandler<T, any>>;\n onDestroyed?: LifecycleHandler<T>;\n /** Called when client disconnects (session persists for TTL) */\n onDisconnect?: DisconnectHandler<T>;\n /** Called when client reconnects with existing session */\n onReconnect?: ReconnectHandler<T>;\n /** Called when session TTL expires */\n onExpire?: ExpireHandler;\n /** Called when any error occurs in the module */\n onError?: ErrorHandler<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 activatedHandler?: LifecycleHandler<T>;\n private deactivatedHandler?: LifecycleHandler<T>;\n private actionHandlers: Map<string, ActionHandler<T, any>> = new Map();\n private destroyedHandler?: LifecycleHandler<T>;\n private disconnectHandler?: DisconnectHandler<T>;\n private reconnectHandler?: ReconnectHandler<T>;\n private expireHandler?: ExpireHandler;\n private errorHandler?: ErrorHandler<T>;\n private template?: string;\n private _registry?: Map<string, HypenModuleDefinition>;\n private dataSourceEntries: Array<{ plugin: DataSourcePlugin; config: unknown }> = [];\n private _stateStore?: StateStore<T>;\n\n constructor(\n initialState: T,\n options?: { persist?: boolean; version?: number; name?: string },\n registry?: Map<string, HypenModuleDefinition>\n ) {\n this.initialState = initialState;\n this.options = options || {};\n this._registry = registry;\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 * Optionally provide a payload type parameter for typed action payloads.\n *\n * @example\n * ```typescript\n * // Typed payload:\n * .onAction<{ amount: number }>(\"add\", ({ action, state }) => {\n * action.payload.amount; // fully typed\n * })\n *\n * // Untyped (payload is unknown):\n * .onAction(\"add\", ({ action, state }) => {\n * action.payload; // unknown\n * })\n * ```\n */\n onAction<P = unknown>(name: string, fn: ActionHandler<T, P>): this {\n this.actionHandlers.set(name, fn as ActionHandler<T, any>);\n return this;\n }\n\n /**\n * Register a handler that runs every time the module becomes the active\n * route target.\n *\n * Unlike `onCreated`, which only runs once per module instance, `onActivated`\n * runs on **every** mount — the first one (right after `onCreated`) and\n * every subsequent re-entry when a cached module is restored by\n * `ManagedRouter`. Use this hook for data refresh, (re)connecting\n * subscriptions, starting timers, and any \"screen became visible\" work\n * that should happen on every navigation to this route.\n *\n * @example\n * ```typescript\n * app\n * .defineState({ items: [], loading: false })\n * .onActivated(async (state) => {\n * state.loading = true;\n * state.items = await fetchItems();\n * state.loading = false;\n * });\n * ```\n */\n onActivated(fn: LifecycleHandler<T>): this {\n this.activatedHandler = fn;\n return this;\n }\n\n /**\n * Register a handler that runs every time the module stops being the\n * active route target.\n *\n * Runs before the module is cached for persistence (when the user\n * navigates to another route) OR before `onDestroyed` if the module is\n * being torn down. Use this for pausing timers, unsubscribing from\n * ephemeral streams, and any \"screen became hidden\" cleanup.\n */\n onDeactivated(fn: LifecycleHandler<T>): this {\n this.deactivatedHandler = 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 * Register a handler for client disconnection\n * Called when client disconnects; session persists for TTL\n * Use this to save state for later restoration\n */\n onDisconnect(fn: DisconnectHandler<T>): this {\n this.disconnectHandler = fn;\n return this;\n }\n\n /**\n * Register a handler for session reconnection\n * Called when client reconnects with an existing session ID\n * Use restore() to hydrate state from saved data\n */\n onReconnect(fn: ReconnectHandler<T>): this {\n this.reconnectHandler = fn;\n return this;\n }\n\n /**\n * Register a handler for session expiration\n * Called when TTL expires and client never reconnected\n * Use this to clean up stored state\n */\n onExpire(fn: ExpireHandler): this {\n this.expireHandler = fn;\n return this;\n }\n\n /**\n * Register an error handler for the module\n * Called when any error occurs in action handlers or lifecycle hooks\n *\n * @example\n * ```typescript\n * app\n * .defineState({ count: 0 })\n * .onAction(\"increment\", ({ state }) => {\n * if (state.count > 100) throw new Error(\"Count too high\");\n * state.count += 1;\n * })\n * .onError(({ error, actionName, state }) => {\n * console.error(`Error in ${actionName}:`, error.message);\n * // Optionally recover\n * if (error.message.includes(\"too high\")) {\n * return { handled: true }; // Don't propagate\n * }\n * // Or retry\n * // return { retry: true };\n * })\n * .build();\n * ```\n *\n * @param fn - Error handler function\n * @returns Builder for chaining\n */\n onError(fn: ErrorHandler<T>): this {\n this.errorHandler = fn;\n return this;\n }\n\n /**\n * Attach a persistent state store.\n * The store handles save/restore lifecycle automatically.\n *\n * @example\n * ```typescript\n * import { durableObjectStore, withKey } from \"@hypen-space/cf\";\n *\n * app\n * .defineState({ user: null, todos: [] }, { name: \"TodoList\" })\n * .persist(durableObjectStore(withKey(state => state.user?.id)))\n * .build();\n * ```\n */\n persist(store: StateStore<T>): this {\n this._stateStore = store;\n return this;\n }\n\n /**\n * Register a data source plugin for live database subscriptions.\n *\n * @example\n * ```typescript\n * import { SpacetimeDBPlugin } from \"@hypen-space/plugin-spacetimedb\";\n *\n * export default app\n * .defineState({ messageText: \"\" })\n * .useDataSource(new SpacetimeDBPlugin(), {\n * uri: \"ws://localhost:3000\",\n * moduleName: \"chat\",\n * tables: [\"user\", \"message\"],\n * })\n * .onAction(\"sendMessage\", async ({ state, dataSources }) => {\n * await dataSources.spacetime.sendMessage(state.messageText);\n * state.messageText = \"\";\n * })\n * .build();\n * ```\n *\n * In Hypen DSL, bind to data source tables with `@provider.table`:\n * ```hypen\n * ForEach(items: @spacetime.message, key: \"id\") {\n * Text(\"@{item.text}\")\n * }\n * ```\n */\n useDataSource<C>(plugin: DataSourcePlugin<C>, config: C): this {\n this.dataSourceEntries.push({ plugin: plugin as DataSourcePlugin, config });\n return this;\n }\n\n /**\n * Define the component's UI template inline (single-file component).\n *\n * Use with the `hypen` tagged template literal and binding proxies:\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 * @param template - The Hypen DSL template string\n * @returns The built module definition (calls build() internally)\n */\n ui(template: string): HypenModuleDefinition<T> {\n this.template = template;\n return this.build();\n }\n\n /**\n * Load a UI template from a .hypen file on disk.\n *\n * @example\n * ```typescript\n * import { app } from \"@hypen-space/core\";\n *\n * export default app\n * .defineState({ count: 0 })\n * .onAction(\"increment\", ({ state }) => { state.count += 1; })\n * .uiFile(\"./counter.hypen\");\n * ```\n *\n * @param path - Path to a .hypen template file\n * @returns The built module definition (calls build() internally)\n */\n uiFile(path: string): HypenModuleDefinition<T> {\n const fs = require(\"fs\");\n this.template = fs.readFileSync(path, \"utf-8\").trim();\n return this.build();\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 const definition: HypenModuleDefinition<T> = {\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 template: this.template,\n dataSources: this.dataSourceEntries.length > 0 ? this.dataSourceEntries : undefined,\n stateStore: this._stateStore,\n handlers: {\n onCreated: this.createdHandler,\n onActivated: this.activatedHandler,\n onDeactivated: this.deactivatedHandler,\n onAction: this.actionHandlers,\n onDestroyed: this.destroyedHandler,\n onDisconnect: this.disconnectHandler,\n onReconnect: this.reconnectHandler,\n onExpire: this.expireHandler,\n onError: this.errorHandler,\n },\n };\n\n // Auto-register in the app registry when the module has a name\n if (this.options.name && this._registry) {\n this._registry.set(this.options.name, definition as HypenModuleDefinition);\n }\n\n return definition;\n }\n}\n\n/**\n * Hypen App API — singleton factory and component registry.\n *\n * Modules built with a `name` are automatically registered here.\n * Consumers (ManagedRouter, RemoteServer, ComponentResolver) read from this\n * registry instead of requiring a separate ModuleRegistry instance.\n */\nexport class HypenApp {\n /** @internal */\n readonly _registry = new Map<string, HypenModuleDefinition>();\n\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, this._registry);\n }\n\n /**\n * Convenience: start a module builder with a name pre-set.\n *\n * @example\n * ```typescript\n * export default app\n * .module(\"Settings\")\n * .defineState({ theme: \"dark\" })\n * .ui(hypen`...`);\n * ```\n */\n module(name: string) {\n const registry = this._registry;\n return {\n defineState: <T>(\n initial: T,\n options?: { persist?: boolean; version?: number }\n ): HypenAppBuilder<T> => {\n return new HypenAppBuilder(initial, { ...options, name }, registry);\n },\n };\n }\n\n // ---------------------------------------------------------------------------\n // Registry API\n // ---------------------------------------------------------------------------\n\n /**\n * Get a registered module definition by component name.\n */\n get(name: string): HypenModuleDefinition | undefined {\n return this._registry.get(name);\n }\n\n /**\n * Check if a module definition is registered.\n */\n has(name: string): boolean {\n return this._registry.has(name);\n }\n\n /**\n * Read-only view of all registered component definitions.\n */\n get components(): ReadonlyMap<string, HypenModuleDefinition> {\n return this._registry;\n }\n\n /**\n * Get all registered component names.\n */\n getNames(): string[] {\n return Array.from(this._registry.keys());\n }\n\n /**\n * Number of registered definitions.\n */\n get size(): number {\n return this._registry.size;\n }\n\n /**\n * Unregister a module definition.\n */\n unregister(name: string): void {\n this._registry.delete(name);\n }\n\n /**\n * Clear all registered definitions.\n */\n clear(): void {\n this._registry.clear();\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 /**\n * True when the module is currently the active route target (i.e.\n * `onActivated` has fired more recently than `onDeactivated`).\n * Used to make `activate()` / `deactivate()` idempotent so the\n * `ManagedRouter` can call them safely regardless of state.\n */\n private isActive = false;\n private router: HypenRouter | null;\n private globalContext?: HypenGlobalContext;\n private stateChangeCallbacks: Array<() => void> = [];\n private dataSourceManager?: DataSourceManager;\n private dataSourceAccessor: DataSourceAccessor = {};\n private stateStore?: StateStore<T>;\n private currentPersistKey: string | null = null;\n private persistDebounceTimer: any;\n private sessionId: string;\n /**\n * Lowercase name used to address this module in the engine. Empty string\n * for anonymous modules (which back the engine's primary module slot).\n */\n private moduleKey: string = \"\";\n\n constructor(\n engine: IEngine,\n definition: HypenModuleDefinition<T>,\n router?: HypenRouter | null,\n globalContext?: HypenGlobalContext,\n sessionId?: string\n ) {\n this.engine = engine;\n this.definition = definition;\n this.router = router ?? null;\n this.globalContext = globalContext;\n this.sessionId = sessionId ?? crypto.randomUUID();\n this.stateStore = definition.stateStore;\n\n // Lowercase module name — used as the engine-side scope key. Empty for\n // anonymous modules (which become the engine's primary module).\n const moduleKey = (definition.name || \"\").toLowerCase();\n this.moduleKey = moduleKey;\n\n // Create observable state that forwards changed paths to the engine.\n // Paths are passed through raw — the engine handles module scoping via\n // the IR's `module_scope` field derived from `module <Name> { ... }` in\n // the DSL.\n this.state = createObservableState<T>(definition.initialState as T & object, {\n onChange: (change: StateChange) => {\n this.engine.updateStateSparse(\n moduleKey || null,\n change.paths,\n change.newValues\n );\n this.stateChangeCallbacks.forEach(cb => cb());\n this.persistIfNeeded();\n },\n });\n\n // Register the module with the engine. Named modules go into the\n // secondary `engine.modules` slot under their lowercase name; anonymous\n // modules become the engine's primary module.\n const snapshot = getStateSnapshot(this.state);\n if (moduleKey) {\n this.engine.registerModule(\n moduleKey,\n definition.actions,\n definition.stateKeys,\n snapshot\n );\n } else {\n this.engine.setModule(\n \"AnonymousModule\",\n definition.actions,\n definition.stateKeys,\n snapshot\n );\n }\n\n // Register action handlers with flexible parameter support\n for (const [actionName, handler] of definition.handlers.onAction) {\n log.debug(`Registering action handler: ${actionName} for module ${definition.name}`);\n this.engine.onAction(actionName, async (action: Action) => {\n log.debug(`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 context: GlobalContext | undefined = this.globalContext\n ? this.createGlobalContextAPI()\n : undefined;\n\n // Use Result type for error handling\n const result = await this.executeAction(actionName, handler, {\n action: actionCtx,\n state: this.state,\n context: context!,\n dataSources: this.dataSourceAccessor,\n });\n\n if (!result.ok) {\n const shouldRethrow = await this.handleError(result.error, { actionName });\n if (shouldRethrow) {\n throw result.error;\n }\n } else {\n log.debug(`Action handler completed: ${actionName}`);\n }\n });\n }\n\n // Auto-register __hypen_bind for .bind() two-way binding support\n this.engine.onAction(\"__hypen_bind\", (action: Action) => {\n const payload = action.payload as { path?: string; value?: unknown } | null;\n if (!payload?.path) return;\n\n const segments = payload.path.split(\".\");\n let target: any = this.state;\n for (let i = 0; i < segments.length - 1; i++) {\n const seg = segments[i]!;\n target = target?.[seg];\n if (target == null) return;\n }\n const lastSeg = segments[segments.length - 1]!;\n target[lastSeg] = payload.value;\n });\n\n // Call onCreated — store the promise so callers can await initialization\n this._readyPromise = this.callCreatedHandler();\n }\n\n /** Promise that resolves when onCreated handler has completed */\n private _readyPromise: Promise<void> = Promise.resolve();\n\n /**\n * Wait for the module's onCreated handler to complete.\n * Call this before renderSource to ensure state is fully initialized.\n */\n async waitForReady(): Promise<void> {\n await this._readyPromise;\n }\n\n /**\n * Mark the module as the active route target and fire `onActivated`.\n *\n * Idempotent: calling `activate()` on an already-active module is a\n * no-op. Internally awaits `waitForReady()` so that `onCreated` always\n * runs to completion before `onActivated` fires, regardless of who\n * calls this method and when.\n *\n * Called by `ManagedRouter` on every route mount — both fresh\n * constructions and re-mounts from the persistence cache.\n */\n async activate(): Promise<void> {\n if (this.isDestroyed || this.isActive) return;\n // Ensure onCreated finishes before onActivated — critical on fresh\n // mounts where the constructor kicks off onCreated asynchronously.\n await this._readyPromise;\n if (this.isDestroyed || this.isActive) return;\n this.isActive = true;\n if (this.definition.handlers.onActivated) {\n const context = this.globalContext ? this.createGlobalContextAPI() : undefined;\n try {\n await this.definition.handlers.onActivated(this.state, context);\n } catch (e) {\n const error = e instanceof HypenError ? e : new ActionError(\"onActivated\", e);\n const shouldRethrow = await this.handleError(error, { lifecycle: \"activated\" });\n if (shouldRethrow) {\n throw error;\n }\n }\n }\n }\n\n /**\n * Mark the module as no longer the active route target and fire\n * `onDeactivated`.\n *\n * Idempotent: calling `deactivate()` on an inactive module is a no-op.\n * Called by `ManagedRouter` before persisting a module for later reuse\n * OR before destroying it.\n */\n async deactivate(): Promise<void> {\n if (this.isDestroyed || !this.isActive) return;\n this.isActive = false;\n if (this.definition.handlers.onDeactivated) {\n const context = this.globalContext ? this.createGlobalContextAPI() : undefined;\n try {\n await this.definition.handlers.onDeactivated(this.state, context);\n } catch (e) {\n const error = e instanceof HypenError ? e : new ActionError(\"onDeactivated\", e);\n const shouldRethrow = await this.handleError(error, { lifecycle: \"deactivated\" });\n if (shouldRethrow) {\n throw error;\n }\n }\n }\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 router: this.router,\n };\n\n // Expose hypen engine for built-in components (if available)\n const ctxRecord = ctx as unknown as Record<string, unknown>;\n if (ctxRecord.__hypenEngine) {\n (api as Record<string, unknown>).__hypenEngine = ctxRecord.__hypenEngine;\n }\n\n return api;\n }\n\n /**\n * Execute an action handler with Result-based error handling\n * Handles both synchronous throws and async rejections\n */\n private async executeAction(\n actionName: string,\n handler: ActionHandler<T, any>,\n ctx: ActionHandlerContext<T>\n ): Promise<Result<void, ActionError>> {\n try {\n // Wrap in try-catch to handle synchronous throws\n const result = handler(ctx);\n // Await in case handler returns a promise\n await result;\n return Ok(undefined);\n } catch (e) {\n return Err(new ActionError(actionName, e));\n }\n }\n\n /**\n * Handle an error with module-level error handler support\n * Falls back to default behavior (emit + log) if no handler or handler doesn't suppress\n * @returns true if the error should be rethrown\n */\n private async handleError(\n error: HypenError,\n context: { actionName?: string; lifecycle?: ErrorContext<T>[\"lifecycle\"] }\n ): Promise<boolean> {\n const errorCtx: ErrorContext<T> = {\n error,\n state: this.state,\n actionName: context.actionName,\n lifecycle: context.lifecycle,\n };\n\n // Call module-level error handler if defined\n if (this.definition.handlers.onError) {\n try {\n const result = await this.definition.handlers.onError(errorCtx);\n\n // Check if error was handled\n if (result && typeof result === \"object\") {\n if (\"handled\" in result && result.handled) {\n // Error was handled, skip default behavior\n return false;\n }\n if (\"rethrow\" in result && result.rethrow) {\n // Signal caller to rethrow\n return true;\n }\n // Note: 'retry' would need to be handled at the action execution level\n // For now, we just continue with default behavior\n }\n } catch (handlerError) {\n // Error in error handler - log and continue with default behavior\n log.error(\"Error in onError handler:\", handlerError);\n }\n }\n\n // Default behavior: emit to global context and log\n if (this.globalContext) {\n const eventContext = context.actionName\n ? `action:${context.actionName}`\n : context.lifecycle\n ? `lifecycle:${context.lifecycle}`\n : \"unknown\";\n\n this.globalContext.emit(\"error\", {\n message: error.message,\n error,\n context: eventContext,\n });\n }\n\n log.error(\n `${context.actionName ? `Action \"${context.actionName}\"` : `Lifecycle \"${context.lifecycle}\"`} error:`,\n error\n );\n\n return false;\n }\n\n /**\n * Re-evaluate the persistence key and debounce saves on state mutation.\n * Handles key transitions (null->value, value->null, value->different value).\n */\n private persistIfNeeded(): void {\n if (!this.stateStore) return;\n\n const store = this.stateStore;\n const newKey = store.resolveKey(\n this.state,\n this.definition.name || \"AnonymousModule\",\n this.sessionId\n );\n\n // Key transition: null -> value (e.g. login)\n if (newKey && !this.currentPersistKey) {\n this.activatePersistence(newKey);\n return;\n }\n\n // Key transition: value -> null (e.g. logout)\n if (!newKey && this.currentPersistKey) {\n this.currentPersistKey = null;\n return; // stop persisting, but don't delete stored data\n }\n\n // Key transition: value -> different value (e.g. account switch)\n if (newKey && newKey !== this.currentPersistKey) {\n this.activatePersistence(newKey);\n return;\n }\n\n // No key = no persistence\n if (!this.currentPersistKey) return;\n\n // Same key — debounced save\n clearTimeout(this.persistDebounceTimer);\n this.persistDebounceTimer = setTimeout(() => {\n const snapshot = getStateSnapshot(this.state);\n store.save(this.currentPersistKey!, snapshot);\n }, 50);\n }\n\n /**\n * Activate persistence for the given key: load stored state and merge.\n */\n private async activatePersistence(key: string): Promise<void> {\n this.currentPersistKey = key;\n const stored = await this.stateStore!.load(key);\n if (stored) {\n // Merge stored over initialState, then apply to live state\n const merged = { ...this.definition.initialState, ...stored };\n Object.assign(this.state, merged); // triggers re-render via proxy\n } else {\n // First time with this key — save current state\n const snapshot = getStateSnapshot(this.state);\n await this.stateStore!.save(key, snapshot);\n }\n }\n\n /**\n * Call the onCreated handler and connect data source plugins\n */\n private async callCreatedHandler(): Promise<void> {\n // Load persisted state before anything else\n if (this.stateStore) {\n const key = this.stateStore.resolveKey(\n this.state,\n this.definition.name || \"AnonymousModule\",\n this.sessionId\n );\n if (key) {\n this.currentPersistKey = key;\n const stored = await this.stateStore.load(key);\n if (stored) {\n const merged = { ...this.definition.initialState, ...stored };\n Object.assign(this.state, merged);\n }\n }\n }\n\n // Initialize data source plugins if any are registered\n if (this.definition.dataSources?.length) {\n // The engine must implement IDataSourceEngine methods\n const dsEngine = this.engine as unknown as IDataSourceEngine;\n this.dataSourceManager = new DataSourceManager(dsEngine);\n\n for (const { plugin, config } of this.definition.dataSources) {\n try {\n await this.dataSourceManager.use(plugin, config);\n // Wrap plugin in a Proxy so unknown method calls forward to plugin.call():\n // dataSources.spacetime.sendMessage(text) → plugin.call(\"sendMessage\", text)\n this.dataSourceAccessor[plugin.name] = new Proxy(plugin, {\n get(target, prop) {\n if (typeof prop === 'string' && !(prop in target)) {\n return (...args: unknown[]) => target.call(prop, ...args);\n }\n return (target as unknown as Record<string | symbol, unknown>)[prop];\n },\n }) as typeof plugin & Record<string, (...args: unknown[]) => Promise<unknown>>;\n } catch (e) {\n log.error(`Failed to connect data source \"${plugin.name}\":`, e);\n }\n }\n }\n\n if (this.definition.handlers.onCreated) {\n const context = this.globalContext ? this.createGlobalContextAPI() : undefined;\n try {\n await this.definition.handlers.onCreated(this.state, context);\n } catch (e) {\n const error = e instanceof HypenError ? e : new ActionError(\"onCreated\", e);\n const shouldRethrow = await this.handleError(error, { lifecycle: \"created\" });\n if (shouldRethrow) {\n throw error;\n }\n }\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 and disconnect all data source plugins\n */\n async destroy(): Promise<void> {\n if (this.isDestroyed) return;\n\n // If this module is still marked as active (e.g. destroy() was called\n // without a preceding deactivate()), fire onDeactivated first so the\n // lifecycle order is always: ...onActivated → onDeactivated → onDestroyed.\n if (this.isActive) {\n await this.deactivate();\n }\n\n // Flush any pending persistence writes before shutdown\n if (this.currentPersistKey && this.stateStore) {\n clearTimeout(this.persistDebounceTimer);\n const snapshot = getStateSnapshot(this.state);\n await this.stateStore.save(this.currentPersistKey, snapshot);\n }\n\n // Disconnect all data source plugins\n if (this.dataSourceManager) {\n try {\n await this.dataSourceManager.disconnectAll();\n } catch (e) {\n log.error(\"Error disconnecting data sources:\", e);\n }\n this.dataSourceManager = undefined;\n this.dataSourceAccessor = {};\n }\n\n if (this.definition.handlers.onDestroyed) {\n try {\n await this.definition.handlers.onDestroyed(this.state);\n } catch (e) {\n const error = e instanceof HypenError ? e : new ActionError(\"onDestroyed\", e);\n const shouldRethrow = await this.handleError(error, { lifecycle: \"destroyed\" });\n if (shouldRethrow) {\n throw error;\n }\n }\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",
|
|
11
|
-
"/**\n * Managed Router — orchestrates module mount/unmount on route changes.\n *\n * When the router navigates to a route:\n * 1. Deactivates and unmounts the previous module (either persisting it for\n * later reuse or destroying it).\n * 2. Mounts the new module (creating it fresh or restoring from cache) and\n * activates it.\n *\n * Module names are used as state prefixes (lowercased) for isolation.\n *\n * ## Persistence (default: on for module-backed routes)\n *\n * By default, any route whose `component` resolves to a registered module\n * definition (or provides one inline via `route.module`) has its module\n * instance **persisted** across navigations. This preserves module state\n * (e.g. fetched data, form inputs, scroll position in state) so that\n * navigating away and back doesn't re-trigger the initial \"loading\" state\n * that usually lives in `onCreated`.\n *\n * Opt out by setting `persist: false` on the module definition. Routes\n * without a module definition are unchanged — they have nothing to persist.\n *\n * ## Persistence cache bound (LRU)\n *\n * The persisted-module cache is an insertion-ordered LRU with a default\n * cap of `DEFAULT_MAX_PERSISTED_MODULES` (= 10). Persisting a module\n * past the cap evicts the least-recently-persisted entry and tears it\n * down via `instance.destroy()` + `unregisterModule()` — the same path a\n * `persist: false` module takes on unmount. Restoring from the cache\n * counts as a touch (the entry is removed on mount and re-inserted on\n * next unmount, placing it at the MRU end).\n *\n * The cap matches the engine's `DEFAULT_ROUTER_CACHE_SIZE` for the\n * Router IR subtree cache, so SDK-level module retention and\n * engine-level DOM-subtree retention stay in lockstep by default.\n * Override via the `maxPersistedModules` constructor option. Pass\n * `Infinity` to disable eviction (only advisable for bounded route\n * sets — otherwise a long session will leak).\n *\n * ## Lifecycle on navigation\n *\n * First visit to a route:\n * `construct → onCreated → onActivated`\n * Navigate away:\n * `onDeactivated` (then either persist in cache OR `onDestroyed`)\n * Revisit (persisted):\n * `onActivated` (only — `onCreated` does not re-run)\n *\n * Use `onActivated` for per-navigation side effects like refreshing data;\n * use `onCreated` for one-time module setup.\n */\n\nimport type { IEngine, HypenModuleDefinition } from \"./app.js\";\nimport { HypenModuleInstance, HypenApp } from \"./app.js\";\nimport type { HypenRouter, RouteState } from \"./router.js\";\nimport type { HypenGlobalContext } from \"./context.js\";\nimport { createLogger } from \"./logger.js\";\n\nconst log = createLogger(\"ManagedRouter\");\n\n/**\n * Default upper bound on `persistedModules`. Mirrors\n * `DEFAULT_ROUTER_CACHE_SIZE` in the engine's Router IR node so the SDK\n * module cache and the engine subtree cache evict in lockstep.\n */\nexport const DEFAULT_MAX_PERSISTED_MODULES = 10;\n\nexport interface RouteDefinition {\n /** Route path pattern (e.g., \"/\", \"/profile/:id\") */\n path: string;\n /** Component name — used to look up in app registry */\n component: string;\n /** Inline module definition (alternative to registry lookup) */\n module?: HypenModuleDefinition;\n}\n\nexport interface ManagedRouterOptions {\n /**\n * Maximum number of persisted module instances retained across\n * navigations. When persistence would push the cache past this cap,\n * the least-recently-persisted entry is destroyed. Defaults to\n * `DEFAULT_MAX_PERSISTED_MODULES`. Pass `Infinity` to disable\n * eviction.\n */\n maxPersistedModules?: number;\n}\n\nexport class ManagedRouter {\n private router: HypenRouter;\n private engine: IEngine;\n private registry: HypenApp;\n private globalContext: HypenGlobalContext;\n private routes: RouteDefinition[] = [];\n private activeModule: HypenModuleInstance | null = null;\n private activeRoute: RouteDefinition | null = null;\n private unsubscribe: (() => void) | null = null;\n /**\n * Cached instances for module-backed routes, keyed by the lowercase\n * module id. Entries are populated on unmount (when `persist` is truthy)\n * and consulted on mount to restore state across navigations.\n *\n * Persistence is the default for any route whose `component` or `module`\n * resolves to a module definition; opt out by setting `persist: false`\n * on the definition.\n *\n * Bounded by `maxPersistedModules`. Map insertion order drives LRU\n * eviction: restoring from the cache removes the entry (so the next\n * persist re-inserts it at the MRU end), and persisting past the cap\n * destroys the oldest entry.\n */\n private persistedModules = new Map<string, HypenModuleInstance>();\n private readonly maxPersistedModules: number;\n /**\n * Serialized chain of in-flight route transitions. Because mount /\n * unmount are now async (they await `onActivated` / `onDeactivated`),\n * back-to-back navigations must not interleave. Each `handleRouteChange`\n * appends to this chain so transitions run strictly in order.\n */\n private navPromise: Promise<void> = Promise.resolve();\n\n constructor(\n router: HypenRouter,\n engine: IEngine,\n registry: HypenApp,\n globalContext: HypenGlobalContext,\n options: ManagedRouterOptions = {}\n ) {\n this.router = router;\n this.engine = engine;\n this.registry = registry;\n this.globalContext = globalContext;\n const cap = options.maxPersistedModules ?? DEFAULT_MAX_PERSISTED_MODULES;\n // Guard against obviously-invalid caps — a zero or negative limit would\n // mean \"never persist\", which the call site should express via\n // `persist: false` on definitions instead.\n this.maxPersistedModules = cap > 0 ? cap : DEFAULT_MAX_PERSISTED_MODULES;\n }\n\n /**\n * Add a route definition.\n */\n addRoute(route: RouteDefinition): this {\n this.routes.push(route);\n return this;\n }\n\n /**\n * Start listening for route changes and mount the initial route.\n *\n * Also installs the `@router.*` engine action handlers so DSL authors can\n * write `.onClick(@router.push, to: \"/x\")` / `@router.back` /\n * `@router.replace` / `@router.forward` and have them dispatched against\n * this session's `HypenRouter` without any per-example wiring. The\n * reserved namespace is set up by `hypen-engine` in `ir/expand.rs`.\n */\n start(): void {\n this.unsubscribe = this.router.onNavigate((routeState: RouteState) => {\n this.handleRouteChange(routeState);\n });\n this.installRouterActions();\n }\n\n /**\n * Register handlers for the reserved `router.*` action namespace.\n *\n * All navigations go through `queueMicrotask` so the router state mutation\n * lands after the engine finishes dispatching the action — synchronous\n * writes would re-enter the engine's WASM state proxy, which the Rust side\n * rejects (\"recursive use of an object\").\n */\n private installRouterActions(): void {\n const router = this.router;\n const defer = (fn: () => void) => queueMicrotask(fn);\n const readTo = (action: { payload?: unknown } | null | undefined): string | null => {\n const payload = action?.payload as Record<string, unknown> | null | undefined;\n const to = payload?.to;\n return typeof to === \"string\" && to.length > 0 ? to : null;\n };\n\n this.engine.onAction(\"router.push\", (action) => {\n const to = readTo(action);\n if (to) defer(() => router.push(to));\n });\n this.engine.onAction(\"router.replace\", (action) => {\n const to = readTo(action);\n if (to) defer(() => router.replace(to));\n });\n this.engine.onAction(\"router.back\", () => {\n defer(() => router.back());\n });\n this.engine.onAction(\"router.forward\", () => {\n defer(() => router.forward());\n });\n }\n\n /**\n * Stop listening and unmount the active module.\n * Also destroys all persisted modules.\n *\n * Waits for any in-flight navigation to settle before tearing down so\n * lifecycle hooks always complete in order.\n */\n async stop(): Promise<void> {\n if (this.unsubscribe) {\n this.unsubscribe();\n this.unsubscribe = null;\n }\n\n // Wait for any in-flight navigation before tearing down.\n const cleanup = this.navPromise\n .catch(() => {\n /* previous navigation errors already reported */\n })\n .then(async () => {\n await this.unmountActive();\n\n // Destroy all persisted modules on full stop. Instances in this\n // map are inactive (they were deactivated when persisted), so\n // `destroy()` just fires `onDestroyed`.\n for (const [moduleId, instance] of this.persistedModules) {\n log.debug(`Destroying persisted module on stop: ${moduleId}`);\n try {\n await instance.destroy();\n } catch (e) {\n log.error(`Error destroying persisted module ${moduleId}:`, e);\n }\n this.globalContext.unregisterModule(moduleId);\n }\n this.persistedModules.clear();\n });\n\n this.navPromise = cleanup;\n await cleanup;\n\n // Clean up router event listeners\n this.router.dispose();\n }\n\n /**\n * Returns a promise that resolves once all currently-queued route\n * transitions have finished. Useful in tests to await lifecycle\n * ordering without reaching into internals.\n */\n async waitForNavigation(): Promise<void> {\n try {\n await this.navPromise;\n } catch {\n /* navigation errors are logged; callers don't need to rethrow */\n }\n }\n\n /**\n * Get the currently active module instance.\n */\n getActiveModule(): HypenModuleInstance | null {\n return this.activeModule;\n }\n\n /**\n * Get the currently active route.\n */\n getActiveRoute(): RouteDefinition | null {\n return this.activeRoute;\n }\n\n private handleRouteChange(routeState: RouteState): void {\n // Chain onto the in-flight navigation promise so transitions run\n // strictly in order. Async activate/deactivate hooks otherwise make\n // it possible for a late `A → B` to finish before an earlier `B → A`.\n this.navPromise = this.navPromise\n .catch((e) => {\n log.error(\"Previous navigation failed:\", e);\n })\n .then(() => this.processRouteChange(routeState));\n }\n\n private async processRouteChange(routeState: RouteState): Promise<void> {\n const path = routeState.currentPath;\n const matched = this.matchRoute(path);\n\n if (!matched) {\n log.debug(`No route matched for path: ${path}`);\n await this.unmountActive();\n return;\n }\n\n // If same route, no need to remount. Still a no-op for same-path\n // navigations (e.g. reselecting the active tab).\n if (this.activeRoute && this.activeRoute.path === matched.path) {\n return;\n }\n\n // Unmount old, mount new.\n await this.unmountActive();\n await this.mount(matched);\n }\n\n private matchRoute(path: string): RouteDefinition | null {\n for (const route of this.routes) {\n if (this.router.matchPath(route.path, path) !== null) {\n return route;\n }\n }\n return null;\n }\n\n private async mount(route: RouteDefinition): Promise<void> {\n // Look up module definition: inline first, then registry\n const definition = route.module || this.registry.get(route.component);\n if (!definition) {\n log.debug(`No module definition found for component: ${route.component}`);\n this.activeRoute = route;\n return;\n }\n\n // Ensure the definition has a name for state namespacing\n const namedDef = {\n ...definition,\n name: definition.name || route.component.toLowerCase(),\n };\n\n const moduleId = namedDef.name!.toLowerCase();\n\n // Check for a persisted instance first. If we hit the cache, we reuse\n // its state verbatim — `onCreated` has already fired (once) and\n // activate() below will fire `onActivated` without re-running the\n // one-time setup.\n const persisted = this.persistedModules.get(moduleId);\n if (persisted) {\n log.debug(`Restoring persisted module: ${moduleId} for route: ${route.path}`);\n this.activeModule = persisted;\n this.activeRoute = route;\n // Remove from the cache while it's active so that a concurrent\n // navigation can't double-mount the same instance.\n this.persistedModules.delete(moduleId);\n await persisted.activate();\n return;\n }\n\n log.debug(`Mounting module: ${namedDef.name} for route: ${route.path}`);\n\n const instance = new HypenModuleInstance(\n this.engine,\n namedDef as HypenModuleDefinition<object>,\n this.router,\n this.globalContext\n );\n\n // Register in global context under the module name (lowercase)\n this.globalContext.registerModule(moduleId, instance);\n\n this.activeModule = instance;\n this.activeRoute = route;\n\n // Fire `onActivated` after `onCreated` resolves. `activate()` awaits\n // the instance's internal readiness promise, so this is safe even\n // though the constructor kicks off `onCreated` asynchronously.\n await instance.activate();\n }\n\n private async unmountActive(): Promise<void> {\n if (!this.activeModule || !this.activeRoute) {\n this.activeModule = null;\n this.activeRoute = null;\n return;\n }\n\n const active = this.activeModule;\n const route = this.activeRoute;\n const definition = route.module || this.registry.get(route.component);\n const moduleId = (definition?.name || route.component).toLowerCase();\n\n // Persistence default: any route backed by a module definition\n // persists unless the definition explicitly opts out.\n //\n // definition present & persist !== false → cache the instance\n // definition present & persist === false → destroy the instance\n // definition missing → nothing to persist\n //\n // This is the new default behavior — prior to this change, persist\n // was opt-in via `persist: true`. Modules that relied on a fresh\n // instance on every navigation should set `persist: false` or move\n // per-navigation work into the new `onActivated` hook.\n const persist = definition != null && definition.persist !== false;\n\n // Clear the active slot *before* firing lifecycle hooks so the\n // module cannot observe itself as \"active\" from inside onDeactivated.\n this.activeModule = null;\n this.activeRoute = null;\n\n // Always deactivate first — regardless of whether we persist or\n // destroy — so `onDeactivated → (onDestroyed)` ordering holds.\n try {\n await active.deactivate();\n } catch (e) {\n log.error(`Error deactivating module ${moduleId}:`, e);\n }\n\n if (persist) {\n log.debug(`Persisting module: ${moduleId}`);\n // If this id is already cached (e.g. after being destroyed and\n // re-activated without passing through mount(), though rare),\n // delete first so the re-insert places it at the MRU end.\n this.persistedModules.delete(moduleId);\n this.persistedModules.set(moduleId, active);\n await this.evictPersistedOverflow();\n // Keep registered in GlobalContext so other modules can still\n // access its state while it's off-screen.\n } else {\n log.debug(`Unmounting module: ${moduleId}`);\n try {\n await active.destroy();\n } catch (e) {\n log.error(`Error destroying module ${moduleId}:`, e);\n }\n this.globalContext.unregisterModule(moduleId);\n }\n }\n\n /**\n * Trim `persistedModules` down to `maxPersistedModules` by destroying\n * the oldest entries (FIFO in Map insertion order, which tracks LRU\n * because `mount()` removes on restore and `unmountActive()` re-inserts\n * at the MRU end on every persist).\n *\n * Errors during eviction are logged — one misbehaving `onDestroyed` hook\n * must not block the router from shrinking the cache on the next\n * navigation.\n */\n private async evictPersistedOverflow(): Promise<void> {\n while (this.persistedModules.size > this.maxPersistedModules) {\n const oldest = this.persistedModules.keys().next();\n if (oldest.done) break;\n const oldestId = oldest.value;\n const evicted = this.persistedModules.get(oldestId)!;\n this.persistedModules.delete(oldestId);\n log.debug(`Evicting persisted module (LRU): ${oldestId}`);\n try {\n await evicted.destroy();\n } catch (e) {\n log.error(`Error destroying evicted module ${oldestId}:`, e);\n }\n this.globalContext.unregisterModule(oldestId);\n }\n }\n}\n"
|
|
12
5
|
],
|
|
13
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAiBO,SAAS,EAAK,CAAC,OAA4B;AAAA,EAChD,OAAO,EAAE,IAAI,MAAM,MAAM;AAAA;AAMpB,SAAS,GAAM,CAAC,OAA4B;AAAA,EACjD,OAAO,EAAE,IAAI,OAAO,MAAM;AAAA;AAMrB,SAAS,IAAU,CAAC,QAAwD;AAAA,EACjF,OAAO,OAAO;AAAA;AAMT,SAAS,KAAW,CAAC,QAAyD;AAAA,EACnF,OAAO,CAAC,OAAO;AAAA;AAMjB,eAAsB,WAAyB,CAC7C,SACA,UACuB;AAAA,EACvB,IAAI;AAAA,IACF,MAAM,QAAQ,MAAM;AAAA,IACpB,OAAO,GAAG,KAAK;AAAA,IACf,OAAO,GAAG;AAAA,IACV,IAAI,UAAU;AAAA,MACZ,OAAO,IAAI,SAAS,CAAC,CAAC;AAAA,IACxB;AAAA,IACA,OAAO,IAAI,CAAM;AAAA;AAAA;AAOd,SAAS,OAAqB,CACnC,IACA,UACc;AAAA,EACd,IAAI;AAAA,IACF,OAAO,GAAG,GAAG,CAAC;AAAA,IACd,OAAO,GAAG;AAAA,IACV,IAAI,UAAU;AAAA,MACZ,OAAO,IAAI,SAAS,CAAC,CAAC;AAAA,IACxB;AAAA,IACA,OAAO,IAAI,CAAM;AAAA;AAAA;AAOd,SAAS,GAAY,CAC1B,QACA,IACc;AAAA,EACd,IAAI,OAAO,IAAI;AAAA,IACb,OAAO,GAAG,GAAG,OAAO,KAAK,CAAC;AAAA,EAC5B;AAAA,EACA,OAAO;AAAA;AAMF,SAAS,MAAe,CAC7B,QACA,IACc;AAAA,EACd,IAAI,CAAC,OAAO,IAAI;AAAA,IACd,OAAO,IAAI,GAAG,OAAO,KAAK,CAAC;AAAA,EAC7B;AAAA,EACA,OAAO;AAAA;AAMF,SAAS,OAAgB,CAC9B,QACA,IACc;AAAA,EACd,IAAI,OAAO,IAAI;AAAA,IACb,OAAO,GAAG,OAAO,KAAK;AAAA,EACxB;AAAA,EACA,OAAO;AAAA;AAMF,SAAS,MAAY,CAAC,QAAyB;AAAA,EACpD,IAAI,OAAO,IAAI;AAAA,IACb,OAAO,OAAO;AAAA,EAChB;AAAA,EACA,MAAM,OAAO;AAAA;AAMR,SAAS,QAAc,CAAC,QAAsB,cAAoB;AAAA,EACvE,IAAI,OAAO,IAAI;AAAA,IACb,OAAO,OAAO;AAAA,EAChB;AAAA,EACA,OAAO;AAAA;AAMF,SAAS,YAAkB,CAAC,QAAsB,IAAwB;AAAA,EAC/E,IAAI,OAAO,IAAI;AAAA,IACb,OAAO,OAAO;AAAA,EAChB;AAAA,EACA,OAAO,GAAG,OAAO,KAAK;AAAA;AAMjB,SAAS,KAAc,CAC5B,QACA,UAIG;AAAA,EACH,IAAI,OAAO,IAAI;AAAA,IACb,OAAO,SAAS,GAAG,OAAO,KAAK;AAAA,EACjC;AAAA,EACA,OAAO,SAAS,IAAI,OAAO,KAAK;AAAA;AAO3B,SAAS,GAAS,CAAC,SAAyC;AAAA,EACjE,MAAM,SAAc,CAAC;AAAA,EACrB,WAAW,UAAU,SAAS;AAAA,IAC5B,IAAI,CAAC,OAAO,IAAI;AAAA,MACd,OAAO;AAAA,IACT;AAAA,IACA,OAAO,KAAK,OAAO,KAAK;AAAA,EAC1B;AAAA,EACA,OAAO,GAAG,MAAM;AAAA;AAAA;AAMX,MAAM,mBAAmB,MAAM;AAAA,EAC3B;AAAA,EACA;AAAA,EACS;AAAA,EAElB,WAAW,CACT,MACA,SACA,SACA;AAAA,IACA,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA,IACZ,KAAK,UAAU,SAAS;AAAA,IACxB,KAAK,QAAQ,SAAS;AAAA,IAGtB,OAAO,eAAe,MAAM,WAAW,SAAS;AAAA;AAEpD;AAAA;AAKO,MAAM,oBAAoB,WAAW;AAAA,EACjC;AAAA,EAET,WAAW,CAAC,YAAoB,OAAiB;AAAA,IAC/C,MACE,gBACA,mBAAmB,uBAAuB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KAC/F;AAAA,MACE,SAAS,EAAE,WAAW;AAAA,MACtB,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,IAC1C,CACF;AAAA,IACA,KAAK,OAAO;AAAA,IACZ,KAAK,aAAa;AAAA;AAEtB;AAAA;AAKO,MAAM,wBAAwB,WAAW;AAAA,EACrC;AAAA,EACA;AAAA,EAET,WAAW,CAAC,KAAa,OAAiB,SAAkB;AAAA,IAC1D,MACE,oBACA,kBAAkB,cAAc,UAAU,aAAa,aAAa,OAClE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KAEvD;AAAA,MACE,SAAS,EAAE,KAAK,QAAQ;AAAA,MACxB,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,IAC1C,CACF;AAAA,IACA,KAAK,OAAO;AAAA,IACZ,KAAK,MAAM;AAAA,IACX,KAAK,UAAU;AAAA;AAEnB;AAAA;AAKO,MAAM,mBAAmB,WAAW;AAAA,EAChC;AAAA,EAET,WAAW,CAAC,SAAiB,MAAe,OAAiB;AAAA,IAC3D,MAAM,eAAe,SAAS;AAAA,MAC5B,SAAS,EAAE,KAAK;AAAA,MAChB,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,IAC1C,CAAC;AAAA,IACD,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA;AAEhB;AAAA;AAKO,MAAM,mBAAmB,WAAW;AAAA,EAChC;AAAA,EAET,WAAW,CAAC,SAAiB,QAAiB,OAAiB;AAAA,IAC7D,MAAM,eAAe,SAAS;AAAA,MAC5B,SAAS,EAAE,OAAO;AAAA,MAClB,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,IAC1C,CAAC;AAAA,IACD,KAAK,OAAO;AAAA,IACZ,KAAK,SAAS;AAAA;AAElB;AAAA;AAKO,MAAM,oBAAoB,WAAW;AAAA,EAC1C,WAAW,CAAC,SAAiB,OAAiB;AAAA,IAC5C,MAAM,gBAAgB,SAAS;AAAA,MAC7B,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,IAC1C,CAAC;AAAA,IACD,KAAK,OAAO;AAAA;AAEhB;AAMO,SAAS,mBAAmB,CAAC,KAA0B;AAAA,EAE5D,IAAI,OAAO,OAAO,QAAQ,YAAY,aAAa,OAAO,UAAU,KAAK;AAAA,IACvE,MAAM,aAAa;AAAA,IACnB,QAAQ,WAAW;AAAA,WACZ;AAAA,QAAc,OAAO,IAAI,WAAW,WAAW,OAAO;AAAA,WACtD;AAAA,QAAc,OAAO,IAAI,WAAW,WAAW,OAAO;AAAA,WACtD;AAAA,QAAe,OAAO,IAAI,YAAY,WAAW,OAAO;AAAA,WACxD;AAAA,QAAe,OAAO,IAAI,WAAW,gBAAgB,WAAW,OAAO;AAAA;AAAA,QACnE,OAAO,IAAI,WAAW,iBAAiB,WAAW,OAAO;AAAA;AAAA,EAEtE;AAAA,EACA,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,EAE/D,IAAI,QAAQ,WAAW,cAAc,GAAG;AAAA,IACtC,OAAO,IAAI,WAAW,OAAO;AAAA,EAC/B;AAAA,EACA,IAAI,QAAQ,WAAW,gBAAgB,KAAK,QAAQ,WAAW,sBAAsB,GAAG;AAAA,IACtF,OAAO,IAAI,WAAW,OAAO;AAAA,EAC/B;AAAA,EACA,IAAI,QAAQ,WAAW,wBAAwB,GAAG;AAAA,IAChD,OAAO,IAAI,YAAY,OAAO;AAAA,EAChC;AAAA,EAEA,OAAO,IAAI,YAAY,OAAO;AAAA;;;AC1JzB,MAAM,kBAAkB;AAAA,EACrB,UAAU,IAAI;AAAA,EACd,UAAU,IAAI;AAAA,EAEd,QAAQ,IAAI;AAAA,EACZ;AAAA,EAER,WAAW,CAAC,QAA2B;AAAA,IACrC,KAAK,SAAS;AAAA;AAAA,OASV,IAAM,CAAC,QAA6B,QAA0B;AAAA,IAClE,QAAQ,SAAS;AAAA,IAGjB,KAAK,MAAM,IAAI,MAAM,CAAC,CAAC;AAAA,IAGvB,KAAK,QAAQ,IAAI,MAAM,MAA0B;AAAA,IACjD,KAAK,QAAQ,IAAI,MAAM,MAAM;AAAA,IAI7B,MAAM,OAAO,QAAQ,QAAQ,CAAC,WAA6B;AAAA,MAEzD,MAAM,UAAU,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC;AAAA,MACzC,WAAW,QAAQ,OAAO,OAAO;AAAA,QAC/B,IAAI,QAAQ,OAAO,QAAQ;AAAA,UACzB,QAAQ,QAAQ,OAAO,OAAO;AAAA,QAChC;AAAA,MACF;AAAA,MACA,KAAK,MAAM,IAAI,MAAM,OAAO;AAAA,MAG5B,KAAK,OAAO,WAAW,MAAM,OAAO;AAAA,KACrC;AAAA;AAAA,EAOH,GAAkD,CAAC,MAA6B;AAAA,IAC9E,OAAO,KAAK,QAAQ,IAAI,IAAI;AAAA;AAAA,EAI9B,GAAG,CAAC,MAAuB;AAAA,IACzB,OAAO,KAAK,QAAQ,IAAI,IAAI;AAAA;AAAA,EAI9B,QAAQ,GAAa;AAAA,IACnB,OAAO,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA;AAAA,EAIvC,SAAS,CAAC,MAA4C;AAAA,IACpD,OAAO,KAAK,QAAQ,IAAI,IAAI,GAAG;AAAA;AAAA,OAM3B,OAAM,CAAC,MAA6B;AAAA,IACxC,MAAM,SAAS,KAAK,QAAQ,IAAI,IAAI;AAAA,IACpC,IAAI,QAAQ;AAAA,MACV,MAAM,OAAO,WAAW;AAAA,MACxB,KAAK,QAAQ,OAAO,IAAI;AAAA,MACxB,KAAK,QAAQ,OAAO,IAAI;AAAA,MACxB,KAAK,MAAM,OAAO,IAAI;AAAA,MACtB,KAAK,OAAO,cAAc,IAAI;AAAA,IAChC;AAAA;AAAA,OAMI,cAAa,GAAkB;AAAA,IACnC,MAAM,QAAQ,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA,IAC5C,MAAM,QAAQ,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,OAAO,IAAI,CAAC,CAAC;AAAA;AAE5D;;;AC/MA,SAAS,YAAY,CAAC,MAAqB;AAAA,EACzC,MAAM,IAAI,MACR,wCAAwC,mDACtC,4FACJ;AAAA;AAGF,IAAI,UAAwB;AAAA,EAC1B,WAAW,MAAM,aAAa,WAAW;AAAA,EACzC,WAAW,MAAM,aAAa,WAAW;AAAA,EACzC,SAAS,MAAM,aAAa,SAAS;AAAA,EACrC,SAAS,MAAM,aAAa,SAAS;AAAA,EACrC,SAAS,MAAM,aAAa,SAAS;AAAA,EACrC,YAAY,MAAM,aAAa,YAAY;AAAA,EAC3C,oBAAoB,MAAM,aAAa,oBAAoB;AAAA,EAC3D,oBAAoB,MAAM,aAAa,oBAAoB;AAAA,EAC3D,YAAY,MAAM,aAAa,YAAY;AAAA,EAC3C,UAAU,MAAM,aAAa,UAAU;AACzC;AAWO,SAAS,eAAe,CAAC,MAAiC;AAAA,EAC/D,IAAI,SAAS,MAAM;AAAA,IACjB,UAAU;AAAA,MACR,WAAW,MAAM,aAAa,WAAW;AAAA,MACzC,WAAW,MAAM,aAAa,WAAW;AAAA,MACzC,SAAS,MAAM,aAAa,SAAS;AAAA,MACrC,SAAS,MAAM,aAAa,SAAS;AAAA,MACrC,SAAS,MAAM,aAAa,SAAS;AAAA,MACrC,YAAY,MAAM,aAAa,YAAY;AAAA,MAC3C,oBAAoB,MAAM,aAAa,oBAAoB;AAAA,MAC3D,oBAAoB,MAAM,aAAa,oBAAoB;AAAA,MAC3D,YAAY,MAAM,aAAa,YAAY;AAAA,MAC3C,UAAU,MAAM,aAAa,UAAU;AAAA,IACzC;AAAA,IACA;AAAA,EACF;AAAA,EACA,UAAU;AAAA;AAOL,IAAM,WAAyB;AAAA,EACpC,WAAW,CAAC,GAAG,GAAG,MAAM,QAAQ,UAAU,GAAG,GAAG,CAAC;AAAA,EACjD,WAAW,CAAC,GAAG,SAAS,QAAQ,UAAU,GAAG,IAAI;AAAA,EACjD,SAAS,CAAC,GAAG,MAAM,QAAQ,QAAQ,GAAG,CAAC;AAAA,EACvC,SAAS,CAAC,GAAG,MAAM,QAAQ,QAAQ,GAAG,CAAC;AAAA,EACvC,SAAS,CAAC,GAAG,GAAG,OAAO,QAAQ,QAAQ,GAAG,GAAG,EAAE;AAAA,EAC/C,YAAY,CAAC,GAAG,MAAM,QAAQ,WAAW,GAAG,CAAC;AAAA,EAC7C,oBAAoB,CAAC,MAAM,QAAQ,mBAAmB,CAAC;AAAA,EACvD,oBAAoB,CAAC,MAAM,QAAQ,mBAAmB,CAAC;AAAA,EACvD,YAAY,CAAC,MAAM,QAAQ,WAAW,CAAC;AAAA,EACvC,UAAU,CAAC,GAAG,MAAM,QAAQ,SAAS,GAAG,CAAC;AAC3C;;;ACjGA,IAAM,WAAW,OAAO,IAAI,eAAe;AAC3C,IAAM,aAAa,OAAO,IAAI,iBAAiB;AAwB/C,SAAS,SAAY,CAAC,KAAW;AAAA,EAE/B,IAAI,QAAQ,QAAQ,OAAO,QAAQ,UAAU;AAAA,IAC3C,OAAO;AAAA,EACT;AAAA,EAGA,IAAI,OAAO,QAAQ,YAAY;AAAA,IAC7B,OAAO;AAAA,EACT;AAAA,EAGA,IAAI,OAAQ,IAAY,kBAAkB,YAAY;AAAA,IACpD,OAAQ,IAAY,cAAc;AAAA,EACpC;AAAA,EAGA,IAAI,eAAe,WAAW,eAAe,SAAS;AAAA,IACpD,OAAO;AAAA,EACT;AAAA,EAGA,MAAM,UAAU,IAAI;AAAA,EAEpB,SAAS,aAAa,CAAC,OAAiB;AAAA,IACtC,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAAA,MAC/C,OAAO;AAAA,IACT;AAAA,IAGA,IAAI,OAAO,UAAU,YAAY;AAAA,MAC/B,OAAO;AAAA,IACT;AAAA,IAGA,IAAI,QAAQ,IAAI,KAAK,GAAG;AAAA,MACtB,OAAO,QAAQ,IAAI,KAAK;AAAA,IAC1B;AAAA,IAGA,IAAI,iBAAiB,WAAW,iBAAiB,SAAS;AAAA,MACxD,OAAO;AAAA,IACT;AAAA,IAIA,IACE,iBAAiB,QACjB,iBAAiB,UACjB,iBAAiB,OACjB,iBAAiB,OACjB,YAAY,OAAO,KAAK,KACxB,iBAAiB,aACjB;AAAA,MACA,IAAI;AAAA,QACF,OAAO,gBAAgB,KAAK;AAAA,QAC5B,MAAM;AAAA,IAGV;AAAA,IAGA,IAAI,MAAM,QAAQ,KAAK,GAAG;AAAA,MACxB,MAAM,WAAkB,CAAC;AAAA,MACzB,QAAQ,IAAI,OAAO,QAAQ;AAAA,MAC3B,SAAS,IAAI,EAAG,IAAI,MAAM,QAAQ,KAAK;AAAA,QACrC,SAAS,KAAK,cAAc,MAAM,EAAE;AAAA,MACtC;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IAGA,MAAM,WAAgB,CAAC;AAAA,IACvB,QAAQ,IAAI,OAAO,QAAQ;AAAA,IAG3B,WAAW,OAAO,OAAO;AAAA,MACvB,IAAI,OAAO,UAAU,eAAe,KAAK,OAAO,GAAG,GAAG;AAAA,QACpD,SAAS,OAAO,cAAc,MAAM,IAAI;AAAA,MAC1C;AAAA,IACF;AAAA,IAGA,MAAM,aAAa,OAAO,sBAAsB,KAAK;AAAA,IACrD,WAAW,OAAO,YAAY;AAAA,MAC5B,SAAS,OAAO,cAAc,MAAM,IAAI;AAAA,IAC1C;AAAA,IAEA,OAAO;AAAA;AAAA,EAGT,OAAO,cAAc,GAAG;AAAA;AAa1B,SAAS,SAAS,CAChB,UACA,UACA,WAAmB,IACN;AAAA,EACb,OAAO,SAAS,UAAU,UAAU,UAAU,QAAQ;AAAA;AAMjD,SAAS,qBAAuC,CACrD,cACA,SACG;AAAA,EAEH,MAAM,OAA6B,WAAW,EAAE,UAAU,MAAM,GAAG;AAAA,EAInE,IAAI,iBAAiB,QAAQ,iBAAiB,WAAW;AAAA,IACvD,eAAe,CAAC;AAAA,EAClB;AAAA,EAIA,IACE,wBAAwB,UACxB,wBAAwB,UACxB,wBAAwB,SACxB;AAAA,IACA,MAAM,IAAI,UACR,8FACA,kDACF;AAAA,EACF;AAAA,EAIA,eAAe,UAAU,YAAY;AAAA,EAGrC,IAAI,eAAe,UAAU,YAAY;AAAA,EACzC,MAAM,aAAa,KAAK,cAAc;AAAA,EAGtC,IAAI,aAAa;AAAA,EACjB,IAAI,gBAAoC;AAAA,EAExC,SAAS,YAAY,GAAG;AAAA,IACtB,IAAI,aAAa;AAAA,MAAG;AAAA,IAGpB,MAAM,SAAS,UAAU,cAAc,OAAO,UAAU;AAAA,IAExD,IAAI,OAAO,MAAM,SAAS,GAAG;AAAA,MAE3B,eAAe,UAAU,KAAK;AAAA,MAG9B,IAAI,eAAe;AAAA,QACjB,OAAO,MAAM,KAAK,GAAG,cAAc,KAAK;AAAA,QACxC,OAAO,OAAO,OAAO,WAAW,cAAc,SAAS;AAAA,QACvD,gBAAgB;AAAA,MAClB;AAAA,MAGA,KAAK,SAAS,MAAM;AAAA,IACtB;AAAA;AAAA,EAIF,IAAI,sBAAsB;AAAA,EAE1B,SAAS,aAAa,GAAG;AAAA,IACvB,IAAI,eAAe,GAAG;AAAA,MAEpB,IAAI,CAAC,qBAAqB;AAAA,QACxB,sBAAsB;AAAA,QACtB,eAAe,MAAM;AAAA,UACnB,sBAAsB;AAAA,UACtB,IAAI,eAAe,GAAG;AAAA,YACpB,aAAa;AAAA,UACf,EAAO;AAAA,SAIR;AAAA,MACH;AAAA,IACF,EAAO;AAAA,MAEL,gBAAgB,iBAAiB,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,EAAE;AAAA;AAAA;AAAA,EAMhE,MAAM,aAAa,IAAI;AAAA,EAEvB,SAAS,WAAW,CAAC,QAAa,UAAuB;AAAA,IAEvD,MAAM,SAAS,WAAW,IAAI,MAAM;AAAA,IACpC,IAAI;AAAA,MAAQ,OAAO;AAAA,IAEnB,MAAM,QAAQ,IAAI,MAAM,QAAQ;AAAA,MAC9B,GAAG,CAAC,KAAK,MAAM;AAAA,QAGb,IAAI,SAAS;AAAA,UAAU,OAAO;AAAA,QAG9B,IAAI,SAAS;AAAA,UAAY,OAAO;AAAA,QAGhC,IAAI,SAAS,gBAAgB;AAAA,UAC3B,OAAO,MAAM;AAAA,YACX;AAAA;AAAA,QAEJ;AAAA,QACA,IAAI,SAAS,cAAc;AAAA,UACzB,OAAO,MAAM;AAAA,YACX;AAAA,YACA,IAAI,eAAe,GAAG;AAAA,cACpB,aAAa;AAAA,YACf;AAAA;AAAA,QAEJ;AAAA,QACA,IAAI,SAAS,iBAAiB;AAAA,UAC5B,OAAO,MAAM,UAAU,GAAG;AAAA,QAC5B;AAAA,QAEA,MAAM,QAAQ,IAAI;AAAA,QAGlB,IAAI,SAAS,OAAO,UAAU,UAAU;AAAA,UAGtC,IAAK,MAAc,WAAW;AAAA,YAC5B,OAAO;AAAA,UACT;AAAA,UAGA,IACE,iBAAiB,QACjB,iBAAiB,UACjB,iBAAiB,OACjB,iBAAiB,OACjB,iBAAiB,WACjB,iBAAiB,SACjB;AAAA,YACA,OAAO;AAAA,UACT;AAAA,UAGA,MAAM,eAAe,WAAW,IAAI,KAAK;AAAA,UACzC,IAAI,cAAc;AAAA,YAChB,OAAO;AAAA,UACT;AAAA,UAGA,MAAM,cAAc,YAAY,OAAO,WAAW,GAAG,YAAY,OAAO,IAAI,MAAM,OAAO,IAAI,CAAC;AAAA,UAC9F,OAAO;AAAA,QACT;AAAA,QAEA,OAAO;AAAA;AAAA,MAGT,GAAG,CAAC,KAAK,MAAM,OAAO;AAAA,QACpB,MAAM,WAAW,IAAI;AAAA,QAIrB,IAAI,SAAS,OAAO,UAAU,YAAa,MAAc,WAAW;AAAA,UAClE,QAAS,MAAc;AAAA,QACzB;AAAA,QAGA,IAAI,QAAQ;AAAA,QAEZ,IAAI,aAAa,OAAO;AAAA,UACtB,cAAc;AAAA,QAChB;AAAA,QAEA,OAAO;AAAA;AAAA,MAGT,cAAc,CAAC,KAAK,MAAM;AAAA,QACxB,MAAM,UAAU,OAAO,UAAU,eAAe,KAAK,KAAK,IAAI;AAAA,QAC9D,MAAM,SAAS,OAAO,IAAI;AAAA,QAC1B,IAAI,SAAS;AAAA,UACX,cAAc;AAAA,QAChB;AAAA,QACA,OAAO;AAAA;AAAA,IAEX,CAAC;AAAA,IAGD,WAAW,IAAI,QAAQ,KAAK;AAAA,IAC5B,OAAO;AAAA;AAAA,EAGT,MAAM,QAAQ,YAAY,cAAc,UAAU;AAAA,EAClD,OAAO;AAAA;AAMF,SAAS,iBAAoB,CAAC,OAAU,IAAsB;AAAA,EACnE,MAAM,IAAI;AAAA,EACV,IAAI,EAAE,gBAAgB,EAAE,YAAY;AAAA,IAClC,EAAE,aAAa;AAAA,IACf,IAAI;AAAA,MACF,GAAG;AAAA,cACH;AAAA,MACA,EAAE,WAAW;AAAA;AAAA,EAEjB,EAAO;AAAA,IACL,GAAG;AAAA;AAAA;AAOA,SAAS,gBAAmB,CAAC,OAAa;AAAA,EAC/C,MAAM,IAAI;AAAA,EACV,IAAI,EAAE,eAAe;AAAA,IACnB,OAAO,EAAE,cAAc;AAAA,EACzB;AAAA,EACA,OAAO,UAAU,KAAK;AAAA;AAMjB,SAAS,YAAY,CAAC,OAAyB;AAAA,EACpD,OAAO,UAAU,QAAQ,OAAO,UAAU,YAAa,MAAc,cAAc;AAAA;AAO9E,SAAS,WAAc,CAAC,OAAa;AAAA,EAC1C,IAAI,UAAU,QAAQ,OAAO,UAAU,YAAa,MAAc,WAAW;AAAA,IAC3E,OAAQ,MAAc;AAAA,EACxB;AAAA,EACA,OAAO;AAAA;;;AChWT,IAAM,kBAA4C;AAAA,EAChD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AACR;AAEA,IAAM,mBAA8D;AAAA,EAClE,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAEA,IAAM,cAAc;AASpB,SAAS,YAAY,GAAY;AAAA,EAC/B,IAAI,OAAO,YAAY,eAAe,QAAQ,KAAK;AAAA,IACjD,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA;AAMT,IAAI,SAAuB;AAAA,EACzB,OAAO,aAAa,IAAI,UAAU;AAAA,EAClC,QAAQ;AAAA,EACR,YAAY;AACd;AASO,SAAS,WAAW,CAAC,OAAuB;AAAA,EACjD,OAAO,QAAQ;AAAA;AAMV,SAAS,WAAW,GAAa;AAAA,EACtC,OAAO,OAAO;AAAA;AAMT,SAAS,eAAe,CAAC,SAAsC;AAAA,EACpE,SAAS,KAAK,WAAW,QAAQ;AAAA;AAM5B,SAAS,aAAa,GAAS;AAAA,EACpC,OAAO,QAAQ;AAAA;AAMV,SAAS,cAAc,GAAS;AAAA,EACrC,OAAO,QAAQ;AAAA;AAaV,SAAS,YAAY,CAAC,SAAwB;AAAA,EACnD,OAAO,QAAQ,UAAU,UAAU;AAAA;AAM9B,SAAS,WAAW,GAAY;AAAA,EACrC,OAAO,OAAO,UAAU;AAAA;AAO1B,SAAS,SAAS,CAAC,OAA0B;AAAA,EAC3C,OAAO,gBAAgB,UAAU,gBAAgB,OAAO;AAAA;AAG1D,SAAS,SAAS,CAAC,KAAa,OAAyB;AAAA,EACvD,MAAM,YAAY,OAAO,aAAa,GAAG,IAAI,KAAK,EAAE,YAAY,OAAO;AAAA,EAEvE,IAAI,OAAO,UAAU,UAAU,QAAQ;AAAA,IACrC,MAAM,QAAQ,iBAAiB;AAAA,IAC/B,OAAO,GAAG,YAAY,SAAS,OAAO;AAAA,EACxC;AAAA,EAEA,OAAO,GAAG,aAAa;AAAA;AAAA;AAiBlB,MAAM,OAAO;AAAA,EACD;AAAA,EAEjB,WAAW,CAAC,KAAa;AAAA,IACvB,KAAK,MAAM;AAAA;AAAA,EAGb,KAAK,IAAI,MAAuB;AAAA,IAC9B,IAAI,CAAC,UAAU,OAAO;AAAA,MAAG;AAAA,IAEzB,IAAI,OAAO,SAAS;AAAA,MAClB,OAAO,QAAQ,MAAM,KAAK,KAAK,GAAG,IAAI;AAAA,IACxC,EAAO;AAAA,MACL,QAAQ,IAAI,UAAU,KAAK,KAAK,OAAO,GAAG,GAAG,IAAI;AAAA;AAAA;AAAA,EAIrD,IAAI,IAAI,MAAuB;AAAA,IAC7B,IAAI,CAAC,UAAU,MAAM;AAAA,MAAG;AAAA,IAExB,IAAI,OAAO,SAAS;AAAA,MAClB,OAAO,QAAQ,KAAK,KAAK,KAAK,GAAG,IAAI;AAAA,IACvC,EAAO;AAAA,MACL,QAAQ,KAAK,UAAU,KAAK,KAAK,MAAM,GAAG,GAAG,IAAI;AAAA;AAAA;AAAA,EAIrD,IAAI,IAAI,MAAuB;AAAA,IAC7B,IAAI,CAAC,UAAU,MAAM;AAAA,MAAG;AAAA,IAExB,IAAI,OAAO,SAAS;AAAA,MAClB,OAAO,QAAQ,KAAK,KAAK,KAAK,GAAG,IAAI;AAAA,IACvC,EAAO;AAAA,MACL,QAAQ,KAAK,UAAU,KAAK,KAAK,MAAM,GAAG,GAAG,IAAI;AAAA;AAAA;AAAA,EAIrD,KAAK,IAAI,MAAuB;AAAA,IAC9B,IAAI,CAAC,UAAU,OAAO;AAAA,MAAG;AAAA,IAEzB,IAAI,OAAO,SAAS;AAAA,MAClB,OAAO,QAAQ,MAAM,KAAK,KAAK,GAAG,IAAI;AAAA,IACxC,EAAO;AAAA,MACL,QAAQ,MAAM,UAAU,KAAK,KAAK,OAAO,GAAG,GAAG,IAAI;AAAA;AAAA;AAAA,EAOvD,IAAO,CAAC,OAAe,IAAgB;AAAA,IACrC,IAAI,CAAC,UAAU,OAAO,GAAG;AAAA,MACvB,OAAO,GAAG;AAAA,IACZ;AAAA,IAEA,MAAM,QAAQ,YAAY,IAAI;AAAA,IAC9B,IAAI;AAAA,MACF,OAAO,GAAG;AAAA,cACV;AAAA,MACA,MAAM,WAAW,YAAY,IAAI,IAAI;AAAA,MACrC,KAAK,MAAM,GAAG,UAAU,SAAS,QAAQ,CAAC,KAAK;AAAA;AAAA;AAAA,OAO7C,UAAY,CAAC,OAAe,IAAkC;AAAA,IAClE,IAAI,CAAC,UAAU,OAAO,GAAG;AAAA,MACvB,OAAO,GAAG;AAAA,IACZ;AAAA,IAEA,MAAM,QAAQ,YAAY,IAAI;AAAA,IAC9B,IAAI;AAAA,MACF,OAAO,MAAM,GAAG;AAAA,cAChB;AAAA,MACA,MAAM,WAAW,YAAY,IAAI,IAAI;AAAA,MACrC,KAAK,MAAM,GAAG,UAAU,SAAS,QAAQ,CAAC,KAAK;AAAA;AAAA;AAAA,EAOnD,KAAK,CAAC,QAAwB;AAAA,IAC5B,OAAO,IAAI,OAAO,GAAG,KAAK,OAAO,QAAQ;AAAA;AAAA,EAM3C,OAAO,CAAC,cAAuB,MAAuB;AAAA,IACpD,IAAI;AAAA,MAAW,KAAK,MAAM,GAAG,IAAI;AAAA;AAAA,EAGnC,MAAM,CAAC,cAAuB,MAAuB;AAAA,IACnD,IAAI;AAAA,MAAW,KAAK,KAAK,GAAG,IAAI;AAAA;AAAA,EAGlC,OAAO,CAAC,cAAuB,MAAuB;AAAA,IACpD,IAAI;AAAA,MAAW,KAAK,MAAM,GAAG,IAAI;AAAA;AAAA,EAM3B,aAAa,IAAI;AAAA,EAEzB,QAAQ,CAAC,QAAgB,MAAuB;AAAA,IAC9C,IAAI,KAAK,WAAW,IAAI,GAAG;AAAA,MAAG;AAAA,IAC9B,KAAK,WAAW,IAAI,GAAG;AAAA,IACvB,KAAK,KAAK,GAAG,IAAI;AAAA;AAAA,EAGnB,SAAS,CAAC,QAAgB,MAAuB;AAAA,IAC/C,IAAI,KAAK,WAAW,IAAI,GAAG;AAAA,MAAG;AAAA,IAC9B,KAAK,WAAW,IAAI,GAAG;AAAA,IACvB,KAAK,MAAM,GAAG,IAAI;AAAA;AAEtB;AAeO,SAAS,YAAY,CAAC,KAAqB;AAAA,EAChD,OAAO,IAAI,OAAO,GAAG;AAAA;AAUhB,IAAM,SAAS,aAAa,OAAO;AAUnC,IAAM,MAAM;AAAA,EACjB,OAAO,CAAC,QAAgB,SAA0B;AAAA,IAChD,IAAI,CAAC,UAAU,OAAO;AAAA,MAAG;AAAA,IACzB,QAAQ,IAAI,UAAU,KAAK,OAAO,GAAG,GAAG,IAAI;AAAA;AAAA,EAG9C,MAAM,CAAC,QAAgB,SAA0B;AAAA,IAC/C,IAAI,CAAC,UAAU,MAAM;AAAA,MAAG;AAAA,IACxB,QAAQ,KAAK,UAAU,KAAK,MAAM,GAAG,GAAG,IAAI;AAAA;AAAA,EAG9C,MAAM,CAAC,QAAgB,SAA0B;AAAA,IAC/C,IAAI,CAAC,UAAU,MAAM;AAAA,MAAG;AAAA,IACxB,QAAQ,KAAK,UAAU,KAAK,MAAM,GAAG,GAAG,IAAI;AAAA;AAAA,EAG9C,OAAO,CAAC,QAAgB,SAA0B;AAAA,IAChD,IAAI,CAAC,UAAU,OAAO;AAAA,MAAG;AAAA,IACzB,QAAQ,MAAM,UAAU,KAAK,OAAO,GAAG,GAAG,IAAI;AAAA;AAElD;AAMO,IAAM,mBAAmB;AAAA,EAC9B,OAAO,aAAa,OAAO;AAAA,EAC3B,QAAQ,aAAa,QAAQ;AAAA,EAC7B,QAAQ,aAAa,QAAQ;AAAA,EAC7B,OAAO,aAAa,OAAO;AAAA,EAC3B,QAAQ,aAAa,QAAQ;AAAA,EAC7B,QAAQ,aAAa,QAAQ;AAAA,EAC7B,UAAU,aAAa,UAAU;AAAA,EACjC,QAAQ,aAAa,QAAQ;AAAA,EAC7B,WAAW,aAAa,WAAW;AAAA,EACnC,QAAQ,aAAa,QAAQ;AAAA,EAC7B,SAAS,aAAa,SAAS;AAAA,EAC/B,WAAW,aAAa,WAAW;AAAA,EACnC,QAAQ,aAAa,QAAQ;AAAA,EAC7B,QAAQ,aAAa,QAAQ;AAAA,EAC7B,OAAO,aAAa,OAAO;AAC7B;;;ACxUA,IAAM,OAAM,aAAa,gBAAgB;AAAA;AAqLlC,MAAM,gBAAmB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAqD,IAAI;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAA0E,CAAC;AAAA,EAC3E;AAAA,EAER,WAAW,CACT,cACA,SACA,UACA;AAAA,IACA,KAAK,eAAe;AAAA,IACpB,KAAK,UAAU,WAAW,CAAC;AAAA,IAC3B,KAAK,YAAY;AAAA;AAAA,EAMnB,SAAS,CAAC,IAA+B;AAAA,IACvC,KAAK,iBAAiB;AAAA,IACtB,OAAO;AAAA;AAAA,EAoBT,QAAqB,CAAC,MAAc,IAA+B;AAAA,IACjE,KAAK,eAAe,IAAI,MAAM,EAA2B;AAAA,IACzD,OAAO;AAAA;AAAA,EAyBT,WAAW,CAAC,IAA+B;AAAA,IACzC,KAAK,mBAAmB;AAAA,IACxB,OAAO;AAAA;AAAA,EAYT,aAAa,CAAC,IAA+B;AAAA,IAC3C,KAAK,qBAAqB;AAAA,IAC1B,OAAO;AAAA;AAAA,EAMT,WAAW,CAAC,IAA+B;AAAA,IACzC,KAAK,mBAAmB;AAAA,IACxB,OAAO;AAAA;AAAA,EAQT,YAAY,CAAC,IAAgC;AAAA,IAC3C,KAAK,oBAAoB;AAAA,IACzB,OAAO;AAAA;AAAA,EAQT,WAAW,CAAC,IAA+B;AAAA,IACzC,KAAK,mBAAmB;AAAA,IACxB,OAAO;AAAA;AAAA,EAQT,QAAQ,CAAC,IAAyB;AAAA,IAChC,KAAK,gBAAgB;AAAA,IACrB,OAAO;AAAA;AAAA,EA8BT,OAAO,CAAC,IAA2B;AAAA,IACjC,KAAK,eAAe;AAAA,IACpB,OAAO;AAAA;AAAA,EAiBT,OAAO,CAAC,OAA4B;AAAA,IAClC,KAAK,cAAc;AAAA,IACnB,OAAO;AAAA;AAAA,EA+BT,aAAgB,CAAC,QAA6B,SAAiB;AAAA,IAC7D,KAAK,kBAAkB,KAAK,EAAE,QAAoC,gBAAO,CAAC;AAAA,IAC1E,OAAO;AAAA;AAAA,EA6BT,EAAE,CAAC,UAA4C;AAAA,IAC7C,KAAK,WAAW;AAAA,IAChB,OAAO,KAAK,MAAM;AAAA;AAAA,EAmBpB,MAAM,CAAC,MAAwC;AAAA,IAC7C,MAAM;AAAA,IACN,KAAK,WAAW,GAAG,aAAa,MAAM,OAAO,EAAE,KAAK;AAAA,IACpD,OAAO,KAAK,MAAM;AAAA;AAAA,EAMpB,KAAK,GAA6B;AAAA,IAEhC,MAAM,YAAY,KAAK,iBAAiB,QAAQ,OAAO,KAAK,iBAAiB,WACzE,OAAO,KAAK,KAAK,YAAY,IAC7B,CAAC;AAAA,IAEL,MAAM,aAAuC;AAAA,MAC3C,MAAM,KAAK,QAAQ;AAAA,MACnB,SAAS,MAAM,KAAK,KAAK,eAAe,KAAK,CAAC;AAAA,MAC9C;AAAA,MACA,SAAS,KAAK,QAAQ;AAAA,MACtB,SAAS,KAAK,QAAQ;AAAA,MACtB,cAAc,KAAK;AAAA,MACnB,UAAU,KAAK;AAAA,MACf,aAAa,KAAK,kBAAkB,SAAS,IAAI,KAAK,oBAAoB;AAAA,MAC1E,YAAY,KAAK;AAAA,MACjB,UAAU;AAAA,QACR,WAAW,KAAK;AAAA,QAChB,aAAa,KAAK;AAAA,QAClB,eAAe,KAAK;AAAA,QACpB,UAAU,KAAK;AAAA,QACf,aAAa,KAAK;AAAA,QAClB,cAAc,KAAK;AAAA,QACnB,aAAa,KAAK;AAAA,QAClB,UAAU,KAAK;AAAA,QACf,SAAS,KAAK;AAAA,MAChB;AAAA,IACF;AAAA,IAGA,IAAI,KAAK,QAAQ,QAAQ,KAAK,WAAW;AAAA,MACvC,KAAK,UAAU,IAAI,KAAK,QAAQ,MAAM,UAAmC;AAAA,IAC3E;AAAA,IAEA,OAAO;AAAA;AAEX;AAAA;AASO,MAAM,SAAS;AAAA,EAEX,YAAY,IAAI;AAAA,EAKzB,WAAc,CACZ,SACA,SACoB;AAAA,IACpB,OAAO,IAAI,gBAAgB,SAAS,SAAS,KAAK,SAAS;AAAA;AAAA,EAc7D,MAAM,CAAC,MAAc;AAAA,IACnB,MAAM,WAAW,KAAK;AAAA,IACtB,OAAO;AAAA,MACL,aAAa,CACX,SACA,YACuB;AAAA,QACvB,OAAO,IAAI,gBAAgB,SAAS,KAAK,SAAS,KAAK,GAAG,QAAQ;AAAA;AAAA,IAEtE;AAAA;AAAA,EAUF,GAAG,CAAC,MAAiD;AAAA,IACnD,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA;AAAA,EAMhC,GAAG,CAAC,MAAuB;AAAA,IACzB,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA;AAAA,MAM5B,UAAU,GAA+C;AAAA,IAC3D,OAAO,KAAK;AAAA;AAAA,EAMd,QAAQ,GAAa;AAAA,IACnB,OAAO,MAAM,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA;AAAA,MAMrC,IAAI,GAAW;AAAA,IACjB,OAAO,KAAK,UAAU;AAAA;AAAA,EAMxB,UAAU,CAAC,MAAoB;AAAA,IAC7B,KAAK,UAAU,OAAO,IAAI;AAAA;AAAA,EAM5B,KAAK,GAAS;AAAA,IACZ,KAAK,UAAU,MAAM;AAAA;AAEzB;AAKO,IAAM,MAAM,IAAI;AAAA;AAKhB,MAAM,oBAA4C;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EAOd,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,uBAA0C,CAAC;AAAA,EAC3C;AAAA,EACA,qBAAyC,CAAC;AAAA,EAC1C;AAAA,EACA,oBAAmC;AAAA,EACnC;AAAA,EACA;AAAA,EAKA,YAAoB;AAAA,EAE5B,WAAW,CACT,QACA,YACA,QACA,eACA,WACA;AAAA,IACA,KAAK,SAAS;AAAA,IACd,KAAK,aAAa;AAAA,IAClB,KAAK,SAAS,UAAU;AAAA,IACxB,KAAK,gBAAgB;AAAA,IACrB,KAAK,YAAY,aAAa,OAAO,WAAW;AAAA,IAChD,KAAK,aAAa,WAAW;AAAA,IAI7B,MAAM,aAAa,WAAW,QAAQ,IAAI,YAAY;AAAA,IACtD,KAAK,YAAY;AAAA,IAMjB,KAAK,QAAQ,sBAAyB,WAAW,cAA4B;AAAA,MAC3E,UAAU,CAAC,WAAwB;AAAA,QACjC,KAAK,OAAO,kBACV,aAAa,MACb,OAAO,OACP,OAAO,SACT;AAAA,QACA,KAAK,qBAAqB,QAAQ,QAAM,GAAG,CAAC;AAAA,QAC5C,KAAK,gBAAgB;AAAA;AAAA,IAEzB,CAAC;AAAA,IAKD,MAAM,WAAW,iBAAiB,KAAK,KAAK;AAAA,IAC5C,IAAI,WAAW;AAAA,MACb,KAAK,OAAO,eACV,WACA,WAAW,SACX,WAAW,WACX,QACF;AAAA,IACF,EAAO;AAAA,MACL,KAAK,OAAO,UACV,mBACA,WAAW,SACX,WAAW,WACX,QACF;AAAA;AAAA,IAIF,YAAY,YAAY,YAAY,WAAW,SAAS,UAAU;AAAA,MAChE,KAAI,MAAM,+BAA+B,yBAAyB,WAAW,MAAM;AAAA,MACnF,KAAK,OAAO,SAAS,YAAY,OAAO,WAAmB;AAAA,QACzD,KAAI,MAAM,yBAAyB,cAAc,MAAM;AAAA,QAEvD,MAAM,YAA2B;AAAA,UAC/B,MAAM,OAAO;AAAA,UACb,SAAS,OAAO;AAAA,UAChB,QAAQ,OAAO;AAAA,QACjB;AAAA,QAEA,MAAM,UAAqC,KAAK,gBAC5C,KAAK,uBAAuB,IAC5B;AAAA,QAGJ,MAAM,SAAS,MAAM,KAAK,cAAc,YAAY,SAAS;AAAA,UAC3D,QAAQ;AAAA,UACR,OAAO,KAAK;AAAA,UACZ;AAAA,UACA,aAAa,KAAK;AAAA,QACpB,CAAC;AAAA,QAED,IAAI,CAAC,OAAO,IAAI;AAAA,UACd,MAAM,gBAAgB,MAAM,KAAK,YAAY,OAAO,OAAO,EAAE,WAAW,CAAC;AAAA,UACzE,IAAI,eAAe;AAAA,YACjB,MAAM,OAAO;AAAA,UACf;AAAA,QACF,EAAO;AAAA,UACL,KAAI,MAAM,6BAA6B,YAAY;AAAA;AAAA,OAEtD;AAAA,IACH;AAAA,IAGA,KAAK,OAAO,SAAS,gBAAgB,CAAC,WAAmB;AAAA,MACvD,MAAM,UAAU,OAAO;AAAA,MACvB,IAAI,CAAC,SAAS;AAAA,QAAM;AAAA,MAEpB,MAAM,WAAW,QAAQ,KAAK,MAAM,GAAG;AAAA,MACvC,IAAI,SAAc,KAAK;AAAA,MACvB,SAAS,IAAI,EAAG,IAAI,SAAS,SAAS,GAAG,KAAK;AAAA,QAC5C,MAAM,MAAM,SAAS;AAAA,QACrB,SAAS,SAAS;AAAA,QAClB,IAAI,UAAU;AAAA,UAAM;AAAA,MACtB;AAAA,MACA,MAAM,UAAU,SAAS,SAAS,SAAS;AAAA,MAC3C,OAAO,WAAW,QAAQ;AAAA,KAC3B;AAAA,IAGD,KAAK,gBAAgB,KAAK,mBAAmB;AAAA;AAAA,EAIvC,gBAA+B,QAAQ,QAAQ;AAAA,OAMjD,aAAY,GAAkB;AAAA,IAClC,MAAM,KAAK;AAAA;AAAA,OAcP,SAAQ,GAAkB;AAAA,IAC9B,IAAI,KAAK,eAAe,KAAK;AAAA,MAAU;AAAA,IAGvC,MAAM,KAAK;AAAA,IACX,IAAI,KAAK,eAAe,KAAK;AAAA,MAAU;AAAA,IACvC,KAAK,WAAW;AAAA,IAChB,IAAI,KAAK,WAAW,SAAS,aAAa;AAAA,MACxC,MAAM,UAAU,KAAK,gBAAgB,KAAK,uBAAuB,IAAI;AAAA,MACrE,IAAI;AAAA,QACF,MAAM,KAAK,WAAW,SAAS,YAAY,KAAK,OAAO,OAAO;AAAA,QAC9D,OAAO,GAAG;AAAA,QACV,MAAM,QAAQ,aAAa,aAAa,IAAI,IAAI,YAAY,eAAe,CAAC;AAAA,QAC5E,MAAM,gBAAgB,MAAM,KAAK,YAAY,OAAO,EAAE,WAAW,YAAY,CAAC;AAAA,QAC9E,IAAI,eAAe;AAAA,UACjB,MAAM;AAAA,QACR;AAAA;AAAA,IAEJ;AAAA;AAAA,OAWI,WAAU,GAAkB;AAAA,IAChC,IAAI,KAAK,eAAe,CAAC,KAAK;AAAA,MAAU;AAAA,IACxC,KAAK,WAAW;AAAA,IAChB,IAAI,KAAK,WAAW,SAAS,eAAe;AAAA,MAC1C,MAAM,UAAU,KAAK,gBAAgB,KAAK,uBAAuB,IAAI;AAAA,MACrE,IAAI;AAAA,QACF,MAAM,KAAK,WAAW,SAAS,cAAc,KAAK,OAAO,OAAO;AAAA,QAChE,OAAO,GAAG;AAAA,QACV,MAAM,QAAQ,aAAa,aAAa,IAAI,IAAI,YAAY,iBAAiB,CAAC;AAAA,QAC9E,MAAM,gBAAgB,MAAM,KAAK,YAAY,OAAO,EAAE,WAAW,cAAc,CAAC;AAAA,QAChF,IAAI,eAAe;AAAA,UACjB,MAAM;AAAA,QACR;AAAA;AAAA,IAEJ;AAAA;AAAA,EAMM,sBAAsB,GAAkB;AAAA,IAC9C,IAAI,CAAC,KAAK,eAAe;AAAA,MACvB,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,MAAM,KAAK;AAAA,IACjB,MAAM,MAAqB;AAAA,MACzB,WAAW,CAAC,OAAe,IAAI,UAAU,EAAE;AAAA,MAC3C,WAAW,CAAC,OAAe,IAAI,UAAU,EAAE;AAAA,MAC3C,cAAc,MAAM,IAAI,aAAa;AAAA,MACrC,gBAAgB,MAAM,IAAI,eAAe;AAAA,MACzC,MAAM,CAAC,OAAe,YAAkB,IAAI,KAAK,OAAO,OAAO;AAAA,MAC/D,IAAI,CAAC,OAAe,YAClB,IAAI,GAAG,OAAO,OAAO;AAAA,MACvB,QAAQ,KAAK;AAAA,IACf;AAAA,IAGA,MAAM,YAAY;AAAA,IAClB,IAAI,UAAU,eAAe;AAAA,MAC1B,IAAgC,gBAAgB,UAAU;AAAA,IAC7D;AAAA,IAEA,OAAO;AAAA;AAAA,OAOK,cAAa,CACzB,YACA,SACA,KACoC;AAAA,IACpC,IAAI;AAAA,MAEF,MAAM,SAAS,QAAQ,GAAG;AAAA,MAE1B,MAAM;AAAA,MACN,OAAO,GAAG,SAAS;AAAA,MACnB,OAAO,GAAG;AAAA,MACV,OAAO,IAAI,IAAI,YAAY,YAAY,CAAC,CAAC;AAAA;AAAA;AAAA,OAS/B,YAAW,CACvB,OACA,SACkB;AAAA,IAClB,MAAM,WAA4B;AAAA,MAChC;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,YAAY,QAAQ;AAAA,MACpB,WAAW,QAAQ;AAAA,IACrB;AAAA,IAGA,IAAI,KAAK,WAAW,SAAS,SAAS;AAAA,MACpC,IAAI;AAAA,QACF,MAAM,SAAS,MAAM,KAAK,WAAW,SAAS,QAAQ,QAAQ;AAAA,QAG9D,IAAI,UAAU,OAAO,WAAW,UAAU;AAAA,UACxC,IAAI,aAAa,UAAU,OAAO,SAAS;AAAA,YAEzC,OAAO;AAAA,UACT;AAAA,UACA,IAAI,aAAa,UAAU,OAAO,SAAS;AAAA,YAEzC,OAAO;AAAA,UACT;AAAA,QAGF;AAAA,QACA,OAAO,cAAc;AAAA,QAErB,KAAI,MAAM,6BAA6B,YAAY;AAAA;AAAA,IAEvD;AAAA,IAGA,IAAI,KAAK,eAAe;AAAA,MACtB,MAAM,eAAe,QAAQ,aACzB,UAAU,QAAQ,eAClB,QAAQ,YACN,aAAa,QAAQ,cACrB;AAAA,MAEN,KAAK,cAAc,KAAK,SAAS;AAAA,QAC/B,SAAS,MAAM;AAAA,QACf;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,IAEA,KAAI,MACF,GAAG,QAAQ,aAAa,WAAW,QAAQ,gBAAgB,cAAc,QAAQ,uBACjF,KACF;AAAA,IAEA,OAAO;AAAA;AAAA,EAOD,eAAe,GAAS;AAAA,IAC9B,IAAI,CAAC,KAAK;AAAA,MAAY;AAAA,IAEtB,MAAM,QAAQ,KAAK;AAAA,IACnB,MAAM,SAAS,MAAM,WACnB,KAAK,OACL,KAAK,WAAW,QAAQ,mBACxB,KAAK,SACP;AAAA,IAGA,IAAI,UAAU,CAAC,KAAK,mBAAmB;AAAA,MACrC,KAAK,oBAAoB,MAAM;AAAA,MAC/B;AAAA,IACF;AAAA,IAGA,IAAI,CAAC,UAAU,KAAK,mBAAmB;AAAA,MACrC,KAAK,oBAAoB;AAAA,MACzB;AAAA,IACF;AAAA,IAGA,IAAI,UAAU,WAAW,KAAK,mBAAmB;AAAA,MAC/C,KAAK,oBAAoB,MAAM;AAAA,MAC/B;AAAA,IACF;AAAA,IAGA,IAAI,CAAC,KAAK;AAAA,MAAmB;AAAA,IAG7B,aAAa,KAAK,oBAAoB;AAAA,IACtC,KAAK,uBAAuB,WAAW,MAAM;AAAA,MAC3C,MAAM,WAAW,iBAAiB,KAAK,KAAK;AAAA,MAC5C,MAAM,KAAK,KAAK,mBAAoB,QAAQ;AAAA,OAC3C,EAAE;AAAA;AAAA,OAMO,oBAAmB,CAAC,KAA4B;AAAA,IAC5D,KAAK,oBAAoB;AAAA,IACzB,MAAM,SAAS,MAAM,KAAK,WAAY,KAAK,GAAG;AAAA,IAC9C,IAAI,QAAQ;AAAA,MAEV,MAAM,SAAS,KAAK,KAAK,WAAW,iBAAiB,OAAO;AAAA,MAC5D,OAAO,OAAO,KAAK,OAAO,MAAM;AAAA,IAClC,EAAO;AAAA,MAEL,MAAM,WAAW,iBAAiB,KAAK,KAAK;AAAA,MAC5C,MAAM,KAAK,WAAY,KAAK,KAAK,QAAQ;AAAA;AAAA;AAAA,OAO/B,mBAAkB,GAAkB;AAAA,IAEhD,IAAI,KAAK,YAAY;AAAA,MACnB,MAAM,MAAM,KAAK,WAAW,WAC1B,KAAK,OACL,KAAK,WAAW,QAAQ,mBACxB,KAAK,SACP;AAAA,MACA,IAAI,KAAK;AAAA,QACP,KAAK,oBAAoB;AAAA,QACzB,MAAM,SAAS,MAAM,KAAK,WAAW,KAAK,GAAG;AAAA,QAC7C,IAAI,QAAQ;AAAA,UACV,MAAM,SAAS,KAAK,KAAK,WAAW,iBAAiB,OAAO;AAAA,UAC5D,OAAO,OAAO,KAAK,OAAO,MAAM;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AAAA,IAGA,IAAI,KAAK,WAAW,aAAa,QAAQ;AAAA,MAEvC,MAAM,WAAW,KAAK;AAAA,MACtB,KAAK,oBAAoB,IAAI,kBAAkB,QAAQ;AAAA,MAEvD,aAAa,QAAQ,qBAAY,KAAK,WAAW,aAAa;AAAA,QAC5D,IAAI;AAAA,UACF,MAAM,KAAK,kBAAkB,IAAI,QAAQ,OAAM;AAAA,UAG/C,KAAK,mBAAmB,OAAO,QAAQ,IAAI,MAAM,QAAQ;AAAA,YACvD,GAAG,CAAC,QAAQ,MAAM;AAAA,cAChB,IAAI,OAAO,SAAS,YAAY,EAAE,QAAQ,SAAS;AAAA,gBACjD,OAAO,IAAI,SAAoB,OAAO,KAAK,MAAM,GAAG,IAAI;AAAA,cAC1D;AAAA,cACA,OAAQ,OAAuD;AAAA;AAAA,UAEnE,CAAC;AAAA,UACD,OAAO,GAAG;AAAA,UACV,KAAI,MAAM,kCAAkC,OAAO,UAAU,CAAC;AAAA;AAAA,MAElE;AAAA,IACF;AAAA,IAEA,IAAI,KAAK,WAAW,SAAS,WAAW;AAAA,MACtC,MAAM,UAAU,KAAK,gBAAgB,KAAK,uBAAuB,IAAI;AAAA,MACrE,IAAI;AAAA,QACF,MAAM,KAAK,WAAW,SAAS,UAAU,KAAK,OAAO,OAAO;AAAA,QAC5D,OAAO,GAAG;AAAA,QACV,MAAM,QAAQ,aAAa,aAAa,IAAI,IAAI,YAAY,aAAa,CAAC;AAAA,QAC1E,MAAM,gBAAgB,MAAM,KAAK,YAAY,OAAO,EAAE,WAAW,UAAU,CAAC;AAAA,QAC5E,IAAI,eAAe;AAAA,UACjB,MAAM;AAAA,QACR;AAAA;AAAA,IAEJ;AAAA;AAAA,EAMF,aAAa,CAAC,UAA4B;AAAA,IACxC,KAAK,qBAAqB,KAAK,QAAQ;AAAA;AAAA,OAMnC,QAAO,GAAkB;AAAA,IAC7B,IAAI,KAAK;AAAA,MAAa;AAAA,IAKtB,IAAI,KAAK,UAAU;AAAA,MACjB,MAAM,KAAK,WAAW;AAAA,IACxB;AAAA,IAGA,IAAI,KAAK,qBAAqB,KAAK,YAAY;AAAA,MAC7C,aAAa,KAAK,oBAAoB;AAAA,MACtC,MAAM,WAAW,iBAAiB,KAAK,KAAK;AAAA,MAC5C,MAAM,KAAK,WAAW,KAAK,KAAK,mBAAmB,QAAQ;AAAA,IAC7D;AAAA,IAGA,IAAI,KAAK,mBAAmB;AAAA,MAC1B,IAAI;AAAA,QACF,MAAM,KAAK,kBAAkB,cAAc;AAAA,QAC3C,OAAO,GAAG;AAAA,QACV,KAAI,MAAM,qCAAqC,CAAC;AAAA;AAAA,MAElD,KAAK,oBAAoB;AAAA,MACzB,KAAK,qBAAqB,CAAC;AAAA,IAC7B;AAAA,IAEA,IAAI,KAAK,WAAW,SAAS,aAAa;AAAA,MACxC,IAAI;AAAA,QACF,MAAM,KAAK,WAAW,SAAS,YAAY,KAAK,KAAK;AAAA,QACrD,OAAO,GAAG;AAAA,QACV,MAAM,QAAQ,aAAa,aAAa,IAAI,IAAI,YAAY,eAAe,CAAC;AAAA,QAC5E,MAAM,gBAAgB,MAAM,KAAK,YAAY,OAAO,EAAE,WAAW,YAAY,CAAC;AAAA,QAC9E,IAAI,eAAe;AAAA,UACjB,MAAM;AAAA,QACR;AAAA;AAAA,IAEJ;AAAA,IAEA,KAAK,cAAc;AAAA;AAAA,EAMrB,QAAQ,GAAM;AAAA,IACZ,OAAO,iBAAiB,KAAK,KAAK;AAAA;AAAA,EAMpC,YAAY,GAAM;AAAA,IAChB,OAAO,KAAK;AAAA;AAAA,EAMd,WAAW,CAAC,OAAyB;AAAA,IACnC,OAAO,OAAO,KAAK,OAAO,KAAK;AAAA;AAEnC;;;ACjkCA,IAAM,OAAM,aAAa,eAAe;AAOjC,IAAM,gCAAgC;AAAA;AAsBtC,MAAM,cAAc;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAA4B,CAAC;AAAA,EAC7B,eAA2C;AAAA,EAC3C,cAAsC;AAAA,EACtC,cAAmC;AAAA,EAenC,mBAAmB,IAAI;AAAA,EACd;AAAA,EAOT,aAA4B,QAAQ,QAAQ;AAAA,EAEpD,WAAW,CACT,QACA,QACA,UACA,eACA,UAAgC,CAAC,GACjC;AAAA,IACA,KAAK,SAAS;AAAA,IACd,KAAK,SAAS;AAAA,IACd,KAAK,WAAW;AAAA,IAChB,KAAK,gBAAgB;AAAA,IACrB,MAAM,MAAM,QAAQ,uBAAuB;AAAA,IAI3C,KAAK,sBAAsB,MAAM,IAAI,MAAM;AAAA;AAAA,EAM7C,QAAQ,CAAC,OAA8B;AAAA,IACrC,KAAK,OAAO,KAAK,KAAK;AAAA,IACtB,OAAO;AAAA;AAAA,EAYT,KAAK,GAAS;AAAA,IACZ,KAAK,cAAc,KAAK,OAAO,WAAW,CAAC,eAA2B;AAAA,MACpE,KAAK,kBAAkB,UAAU;AAAA,KAClC;AAAA,IACD,KAAK,qBAAqB;AAAA;AAAA,EAWpB,oBAAoB,GAAS;AAAA,IACnC,MAAM,SAAS,KAAK;AAAA,IACpB,MAAM,QAAQ,CAAC,OAAmB,eAAe,EAAE;AAAA,IACnD,MAAM,SAAS,CAAC,WAAoE;AAAA,MAClF,MAAM,UAAU,QAAQ;AAAA,MACxB,MAAM,KAAK,SAAS;AAAA,MACpB,OAAO,OAAO,OAAO,YAAY,GAAG,SAAS,IAAI,KAAK;AAAA;AAAA,IAGxD,KAAK,OAAO,SAAS,eAAe,CAAC,WAAW;AAAA,MAC9C,MAAM,KAAK,OAAO,MAAM;AAAA,MACxB,IAAI;AAAA,QAAI,MAAM,MAAM,OAAO,KAAK,EAAE,CAAC;AAAA,KACpC;AAAA,IACD,KAAK,OAAO,SAAS,kBAAkB,CAAC,WAAW;AAAA,MACjD,MAAM,KAAK,OAAO,MAAM;AAAA,MACxB,IAAI;AAAA,QAAI,MAAM,MAAM,OAAO,QAAQ,EAAE,CAAC;AAAA,KACvC;AAAA,IACD,KAAK,OAAO,SAAS,eAAe,MAAM;AAAA,MACxC,MAAM,MAAM,OAAO,KAAK,CAAC;AAAA,KAC1B;AAAA,IACD,KAAK,OAAO,SAAS,kBAAkB,MAAM;AAAA,MAC3C,MAAM,MAAM,OAAO,QAAQ,CAAC;AAAA,KAC7B;AAAA;AAAA,OAUG,KAAI,GAAkB;AAAA,IAC1B,IAAI,KAAK,aAAa;AAAA,MACpB,KAAK,YAAY;AAAA,MACjB,KAAK,cAAc;AAAA,IACrB;AAAA,IAGA,MAAM,UAAU,KAAK,WAClB,MAAM,MAAM,EAEZ,EACA,KAAK,YAAY;AAAA,MAChB,MAAM,KAAK,cAAc;AAAA,MAKzB,YAAY,UAAU,aAAa,KAAK,kBAAkB;AAAA,QACxD,KAAI,MAAM,wCAAwC,UAAU;AAAA,QAC5D,IAAI;AAAA,UACF,MAAM,SAAS,QAAQ;AAAA,UACvB,OAAO,GAAG;AAAA,UACV,KAAI,MAAM,qCAAqC,aAAa,CAAC;AAAA;AAAA,QAE/D,KAAK,cAAc,iBAAiB,QAAQ;AAAA,MAC9C;AAAA,MACA,KAAK,iBAAiB,MAAM;AAAA,KAC7B;AAAA,IAEH,KAAK,aAAa;AAAA,IAClB,MAAM;AAAA,IAGN,KAAK,OAAO,QAAQ;AAAA;AAAA,OAQhB,kBAAiB,GAAkB;AAAA,IACvC,IAAI;AAAA,MACF,MAAM,KAAK;AAAA,MACX,MAAM;AAAA;AAAA,EAQV,eAAe,GAA+B;AAAA,IAC5C,OAAO,KAAK;AAAA;AAAA,EAMd,cAAc,GAA2B;AAAA,IACvC,OAAO,KAAK;AAAA;AAAA,EAGN,iBAAiB,CAAC,YAA8B;AAAA,IAItD,KAAK,aAAa,KAAK,WACpB,MAAM,CAAC,MAAM;AAAA,MACZ,KAAI,MAAM,+BAA+B,CAAC;AAAA,KAC3C,EACA,KAAK,MAAM,KAAK,mBAAmB,UAAU,CAAC;AAAA;AAAA,OAGrC,mBAAkB,CAAC,YAAuC;AAAA,IACtE,MAAM,OAAO,WAAW;AAAA,IACxB,MAAM,UAAU,KAAK,WAAW,IAAI;AAAA,IAEpC,IAAI,CAAC,SAAS;AAAA,MACZ,KAAI,MAAM,8BAA8B,MAAM;AAAA,MAC9C,MAAM,KAAK,cAAc;AAAA,MACzB;AAAA,IACF;AAAA,IAIA,IAAI,KAAK,eAAe,KAAK,YAAY,SAAS,QAAQ,MAAM;AAAA,MAC9D;AAAA,IACF;AAAA,IAGA,MAAM,KAAK,cAAc;AAAA,IACzB,MAAM,KAAK,MAAM,OAAO;AAAA;AAAA,EAGlB,UAAU,CAAC,MAAsC;AAAA,IACvD,WAAW,SAAS,KAAK,QAAQ;AAAA,MAC/B,IAAI,KAAK,OAAO,UAAU,MAAM,MAAM,IAAI,MAAM,MAAM;AAAA,QACpD,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,OAAO;AAAA;AAAA,OAGK,MAAK,CAAC,OAAuC;AAAA,IAEzD,MAAM,aAAa,MAAM,UAAU,KAAK,SAAS,IAAI,MAAM,SAAS;AAAA,IACpE,IAAI,CAAC,YAAY;AAAA,MACf,KAAI,MAAM,6CAA6C,MAAM,WAAW;AAAA,MACxE,KAAK,cAAc;AAAA,MACnB;AAAA,IACF;AAAA,IAGA,MAAM,WAAW;AAAA,SACZ;AAAA,MACH,MAAM,WAAW,QAAQ,MAAM,UAAU,YAAY;AAAA,IACvD;AAAA,IAEA,MAAM,WAAW,SAAS,KAAM,YAAY;AAAA,IAM5C,MAAM,YAAY,KAAK,iBAAiB,IAAI,QAAQ;AAAA,IACpD,IAAI,WAAW;AAAA,MACb,KAAI,MAAM,+BAA+B,uBAAuB,MAAM,MAAM;AAAA,MAC5E,KAAK,eAAe;AAAA,MACpB,KAAK,cAAc;AAAA,MAGnB,KAAK,iBAAiB,OAAO,QAAQ;AAAA,MACrC,MAAM,UAAU,SAAS;AAAA,MACzB;AAAA,IACF;AAAA,IAEA,KAAI,MAAM,oBAAoB,SAAS,mBAAmB,MAAM,MAAM;AAAA,IAEtE,MAAM,WAAW,IAAI,oBACnB,KAAK,QACL,UACA,KAAK,QACL,KAAK,aACP;AAAA,IAGA,KAAK,cAAc,eAAe,UAAU,QAAQ;AAAA,IAEpD,KAAK,eAAe;AAAA,IACpB,KAAK,cAAc;AAAA,IAKnB,MAAM,SAAS,SAAS;AAAA;AAAA,OAGZ,cAAa,GAAkB;AAAA,IAC3C,IAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,aAAa;AAAA,MAC3C,KAAK,eAAe;AAAA,MACpB,KAAK,cAAc;AAAA,MACnB;AAAA,IACF;AAAA,IAEA,MAAM,SAAS,KAAK;AAAA,IACpB,MAAM,QAAQ,KAAK;AAAA,IACnB,MAAM,aAAa,MAAM,UAAU,KAAK,SAAS,IAAI,MAAM,SAAS;AAAA,IACpE,MAAM,YAAY,YAAY,QAAQ,MAAM,WAAW,YAAY;AAAA,IAanE,MAAM,UAAU,cAAc,QAAQ,WAAW,YAAY;AAAA,IAI7D,KAAK,eAAe;AAAA,IACpB,KAAK,cAAc;AAAA,IAInB,IAAI;AAAA,MACF,MAAM,OAAO,WAAW;AAAA,MACxB,OAAO,GAAG;AAAA,MACV,KAAI,MAAM,6BAA6B,aAAa,CAAC;AAAA;AAAA,IAGvD,IAAI,SAAS;AAAA,MACX,KAAI,MAAM,sBAAsB,UAAU;AAAA,MAI1C,KAAK,iBAAiB,OAAO,QAAQ;AAAA,MACrC,KAAK,iBAAiB,IAAI,UAAU,MAAM;AAAA,MAC1C,MAAM,KAAK,uBAAuB;AAAA,IAGpC,EAAO;AAAA,MACL,KAAI,MAAM,sBAAsB,UAAU;AAAA,MAC1C,IAAI;AAAA,QACF,MAAM,OAAO,QAAQ;AAAA,QACrB,OAAO,GAAG;AAAA,QACV,KAAI,MAAM,2BAA2B,aAAa,CAAC;AAAA;AAAA,MAErD,KAAK,cAAc,iBAAiB,QAAQ;AAAA;AAAA;AAAA,OAclC,uBAAsB,GAAkB;AAAA,IACpD,OAAO,KAAK,iBAAiB,OAAO,KAAK,qBAAqB;AAAA,MAC5D,MAAM,SAAS,KAAK,iBAAiB,KAAK,EAAE,KAAK;AAAA,MACjD,IAAI,OAAO;AAAA,QAAM;AAAA,MACjB,MAAM,WAAW,OAAO;AAAA,MACxB,MAAM,UAAU,KAAK,iBAAiB,IAAI,QAAQ;AAAA,MAClD,KAAK,iBAAiB,OAAO,QAAQ;AAAA,MACrC,KAAI,MAAM,oCAAoC,UAAU;AAAA,MACxD,IAAI;AAAA,QACF,MAAM,QAAQ,QAAQ;AAAA,QACtB,OAAO,GAAG;AAAA,QACV,KAAI,MAAM,mCAAmC,aAAa,CAAC;AAAA;AAAA,MAE7D,KAAK,cAAc,iBAAiB,QAAQ;AAAA,IAC9C;AAAA;AAEJ;",
|
|
14
|
-
"debugId": "
|
|
6
|
+
"mappings": "",
|
|
7
|
+
"debugId": "8AB2D709076E914264756E2164756E21",
|
|
15
8
|
"names": []
|
|
16
9
|
}
|
package/dist/portable.js
CHANGED
|
@@ -1,75 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var __export = (target, all) => {
|
|
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/portable.ts
|
|
25
|
-
function notInstalled(name) {
|
|
26
|
-
throw new Error(`[@hypen-space/core] Portable helper "${name}" called before the engine was installed. ` + `Import @hypen-space/server, @hypen-space/web-engine, or call setPortableImpl() before use.`);
|
|
27
|
-
}
|
|
28
|
-
var current = {
|
|
29
|
-
diffState: () => notInstalled("diffState"),
|
|
30
|
-
matchPath: () => notInstalled("matchPath"),
|
|
31
|
-
pathGet: () => notInstalled("pathGet"),
|
|
32
|
-
pathHas: () => notInstalled("pathHas"),
|
|
33
|
-
pathSet: () => notInstalled("pathSet"),
|
|
34
|
-
pathDelete: () => notInstalled("pathDelete"),
|
|
35
|
-
encodeUriComponent: () => notInstalled("encodeUriComponent"),
|
|
36
|
-
decodeUriComponent: () => notInstalled("decodeUriComponent"),
|
|
37
|
-
parseQuery: () => notInstalled("parseQuery"),
|
|
38
|
-
buildUrl: () => notInstalled("buildUrl")
|
|
39
|
-
};
|
|
40
|
-
function setPortableImpl(impl) {
|
|
41
|
-
if (impl === null) {
|
|
42
|
-
current = {
|
|
43
|
-
diffState: () => notInstalled("diffState"),
|
|
44
|
-
matchPath: () => notInstalled("matchPath"),
|
|
45
|
-
pathGet: () => notInstalled("pathGet"),
|
|
46
|
-
pathHas: () => notInstalled("pathHas"),
|
|
47
|
-
pathSet: () => notInstalled("pathSet"),
|
|
48
|
-
pathDelete: () => notInstalled("pathDelete"),
|
|
49
|
-
encodeUriComponent: () => notInstalled("encodeUriComponent"),
|
|
50
|
-
decodeUriComponent: () => notInstalled("decodeUriComponent"),
|
|
51
|
-
parseQuery: () => notInstalled("parseQuery"),
|
|
52
|
-
buildUrl: () => notInstalled("buildUrl")
|
|
53
|
-
};
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
current = impl;
|
|
57
|
-
}
|
|
58
|
-
var portable = {
|
|
59
|
-
diffState: (o, n, b) => current.diffState(o, n, b),
|
|
60
|
-
matchPath: (p, path) => current.matchPath(p, path),
|
|
61
|
-
pathGet: (v, p) => current.pathGet(v, p),
|
|
62
|
-
pathHas: (v, p) => current.pathHas(v, p),
|
|
63
|
-
pathSet: (v, p, nv) => current.pathSet(v, p, nv),
|
|
64
|
-
pathDelete: (v, p) => current.pathDelete(v, p),
|
|
65
|
-
encodeUriComponent: (s) => current.encodeUriComponent(s),
|
|
66
|
-
decodeUriComponent: (s) => current.decodeUriComponent(s),
|
|
67
|
-
parseQuery: (f) => current.parseQuery(f),
|
|
68
|
-
buildUrl: (p, q) => current.buildUrl(p, q)
|
|
69
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
portable,
|
|
3
|
+
setPortableImpl
|
|
4
|
+
} from "./chunk-g830re2c.js";
|
|
5
|
+
import"./chunk-5gtx3pza.js";
|
|
70
6
|
export {
|
|
71
7
|
setPortableImpl,
|
|
72
8
|
portable
|
|
73
9
|
};
|
|
74
10
|
|
|
75
|
-
//# debugId=
|
|
11
|
+
//# debugId=FFF8B7BA79DC6C7664756E2164756E21
|
package/dist/portable.js.map
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": [
|
|
3
|
+
"sources": [],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Portable helper DI seam for `@hypen-space/core`.\n *\n * `@hypen-space/core` is WASM-free: it ships to contexts (tree-shakers,\n * browser remote-client bundles) that must not pull in the 2 MB engine\n * binary. But every Hypen runtime — Node via `@hypen-space/server`,\n * browser SPA via `@hypen-space/web-engine`, tests via the bun preload\n * — composes core with a host that HAS loaded the engine. Those\n * packages call [`setPortableImpl`] at their init time, plugging the\n * canonical Rust-engine impls (`hypen-engine-rs/src/portable/`) into\n * core.\n *\n * There is no TypeScript fallback. A core instance whose portable\n * helpers are called before `setPortableImpl` has run throws a clear\n * error pointing at the fix. Reasons:\n *\n * * Any fallback is a second implementation to maintain, exactly the\n * drift tax this whole refactor eliminated for the other four SDKs.\n * * Core's own consumers of the portable helpers (`HypenRouter.matchPath`,\n * `createObservableState`'s `notifyChange`) are never reached in\n * remote-client-only browser bundles — those bundles drive UI purely\n * from server-pushed patches.\n * * Callers who DO reach the helpers (server, web-engine, tests) always\n * have an engine available.\n */\n\nimport type { StateChange, StatePath } from \"./state\";\n\nexport interface PortableImpl {\n diffState(oldState: any, newState: any, basePath?: string): StateChange;\n matchPath(\n pattern: string,\n path: string,\n ): { params: Record<string, string> } | null;\n pathGet(value: any, path: string): unknown;\n pathHas(value: any, path: string): boolean;\n pathSet(value: any, path: string, newValue: any): any;\n pathDelete(value: any, path: string): { value: any; removed: boolean };\n encodeUriComponent(input: string): string;\n decodeUriComponent(input: string): string;\n parseQuery(fullPath: string): { path: string; query: Record<string, string> };\n buildUrl(path: string, query: Record<string, string>): string;\n}\n\nfunction notInstalled(name: string): never {\n throw new Error(\n `[@hypen-space/core] Portable helper \"${name}\" called before the engine was installed. ` +\n `Import @hypen-space/server, @hypen-space/web-engine, or call setPortableImpl() before use.`,\n );\n}\n\nlet current: PortableImpl = {\n diffState: () => notInstalled(\"diffState\"),\n matchPath: () => notInstalled(\"matchPath\"),\n pathGet: () => notInstalled(\"pathGet\"),\n pathHas: () => notInstalled(\"pathHas\"),\n pathSet: () => notInstalled(\"pathSet\"),\n pathDelete: () => notInstalled(\"pathDelete\"),\n encodeUriComponent: () => notInstalled(\"encodeUriComponent\"),\n decodeUriComponent: () => notInstalled(\"decodeUriComponent\"),\n parseQuery: () => notInstalled(\"parseQuery\"),\n buildUrl: () => notInstalled(\"buildUrl\"),\n};\n\n/**\n * Install the engine-backed [`PortableImpl`]. Called once by\n * `@hypen-space/server` at import time (synchronous wasm-node load) or\n * by `@hypen-space/web-engine` inside `Engine.init()` once the browser\n * wasm module resolves.\n *\n * Passing `null` resets to the \"not installed\" throwing default — used\n * by test teardown when you want to verify the no-engine error path.\n */\nexport function setPortableImpl(impl: PortableImpl | null): void {\n if (impl === null) {\n current = {\n diffState: () => notInstalled(\"diffState\"),\n matchPath: () => notInstalled(\"matchPath\"),\n pathGet: () => notInstalled(\"pathGet\"),\n pathHas: () => notInstalled(\"pathHas\"),\n pathSet: () => notInstalled(\"pathSet\"),\n pathDelete: () => notInstalled(\"pathDelete\"),\n encodeUriComponent: () => notInstalled(\"encodeUriComponent\"),\n decodeUriComponent: () => notInstalled(\"decodeUriComponent\"),\n parseQuery: () => notInstalled(\"parseQuery\"),\n buildUrl: () => notInstalled(\"buildUrl\"),\n };\n return;\n }\n current = impl;\n}\n\n/**\n * Live portable API. Every call dispatches to whatever\n * [`setPortableImpl`] most recently installed.\n */\nexport const portable: PortableImpl = {\n diffState: (o, n, b) => current.diffState(o, n, b),\n matchPath: (p, path) => current.matchPath(p, path),\n pathGet: (v, p) => current.pathGet(v, p),\n pathHas: (v, p) => current.pathHas(v, p),\n pathSet: (v, p, nv) => current.pathSet(v, p, nv),\n pathDelete: (v, p) => current.pathDelete(v, p),\n encodeUriComponent: (s) => current.encodeUriComponent(s),\n decodeUriComponent: (s) => current.decodeUriComponent(s),\n parseQuery: (f) => current.parseQuery(f),\n buildUrl: (p, q) => current.buildUrl(p, q),\n};\n\n// `StatePath` is still part of this module's public surface via\n// re-export; keeping it reachable from `@hypen-space/core/portable`\n// simplifies bindings in server / web-engine adapters.\nexport type { StatePath } from \"./state\";\n"
|
|
6
5
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
6
|
+
"mappings": "",
|
|
7
|
+
"debugId": "FFF8B7BA79DC6C7664756E2164756E21",
|
|
9
8
|
"names": []
|
|
10
9
|
}
|