@yoltra/devtools-ui 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"file":"devtools-ui.esm.js","sources":["../src/context/HubContext.ts","../../../common/temp/node_modules/.pnpm/react@19.1.1/node_modules/react/cjs/react-jsx-runtime.production.js","../../../common/temp/node_modules/.pnpm/react@19.1.1/node_modules/react/cjs/react-jsx-runtime.development.js","../../../common/temp/node_modules/.pnpm/react@19.1.1/node_modules/react/jsx-runtime.js","../src/context/HubProvider.tsx","../src/hooks/useHubConnection.ts","../src/hooks/useEventEmitter.ts","../src/hooks/useEventLog.ts","../src/hooks/useEventReplay.ts","../src/hooks/useStoreMetrics.ts","../src/hooks/useStoreRegistry.ts","../src/utils/apply-patch.ts","../src/hooks/snapshotRetry.ts","../src/hooks/useStoreState.ts","../src/hooks/useStoreSubscriptions.ts","../src/hooks/timeTravelNav.ts","../src/hooks/useTimeTravel.ts","../src/transport/loopback.ts"],"sourcesContent":["/**\n * React context that exposes the DevTools hub connection to the component tree.\n *\n * @remarks\n * This module defines {@link HubContext}, which holds the current\n * {@link HubContextValue}. It is populated by {@link HubProvider} and\n * consumed via the {@link useHubConnection} hook. Accessing the context\n * without a provider returns a safe no-op default.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport { createContext } from \"react\";\nimport type { HubContextValue } from \"../types\";\n\nconst noop = () => {};\n\n/**\n * React context for the DevTools hub connection.\n *\n * @remarks\n * The context ships with an inert default value so that components rendered\n * outside of a {@link HubProvider} do not throw. Consumers should always\n * wrap their tree in a provider before relying on the context value.\n *\n * @example\n * ```tsx\n * import { useContext } from \"react\";\n * import { HubContext } from \"@yoltra/devtools-ui\";\n *\n * function StatusBadge() {\n * const { status } = useContext(HubContext);\n * return <span>{status}</span>;\n * }\n * ```\n *\n * @public\n */\nexport const HubContext = createContext<HubContextValue>({\n status: \"disconnected\",\n send: noop,\n subscribe: () => noop,\n disconnect: noop,\n reconnect: noop,\n});\n","/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\"production\" !== process.env.NODE_ENV &&\n (function () {\n function getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (\n (\"number\" === typeof type.tag &&\n console.error(\n \"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.\"\n ),\n type.$$typeof)\n ) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return (type.displayName || \"Context\") + \".Provider\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n }\n function testStringCoercion(value) {\n return \"\" + value;\n }\n function checkKeyStringCoercion(value) {\n try {\n testStringCoercion(value);\n var JSCompiler_inline_result = !1;\n } catch (e) {\n JSCompiler_inline_result = !0;\n }\n if (JSCompiler_inline_result) {\n JSCompiler_inline_result = console;\n var JSCompiler_temp_const = JSCompiler_inline_result.error;\n var JSCompiler_inline_result$jscomp$0 =\n (\"function\" === typeof Symbol &&\n Symbol.toStringTag &&\n value[Symbol.toStringTag]) ||\n value.constructor.name ||\n \"Object\";\n JSCompiler_temp_const.call(\n JSCompiler_inline_result,\n \"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.\",\n JSCompiler_inline_result$jscomp$0\n );\n return testStringCoercion(value);\n }\n }\n function getTaskName(type) {\n if (type === REACT_FRAGMENT_TYPE) return \"<>\";\n if (\n \"object\" === typeof type &&\n null !== type &&\n type.$$typeof === REACT_LAZY_TYPE\n )\n return \"<...>\";\n try {\n var name = getComponentNameFromType(type);\n return name ? \"<\" + name + \">\" : \"<...>\";\n } catch (x) {\n return \"<...>\";\n }\n }\n function getOwner() {\n var dispatcher = ReactSharedInternals.A;\n return null === dispatcher ? null : dispatcher.getOwner();\n }\n function UnknownOwner() {\n return Error(\"react-stack-top-frame\");\n }\n function hasValidKey(config) {\n if (hasOwnProperty.call(config, \"key\")) {\n var getter = Object.getOwnPropertyDescriptor(config, \"key\").get;\n if (getter && getter.isReactWarning) return !1;\n }\n return void 0 !== config.key;\n }\n function defineKeyPropWarningGetter(props, displayName) {\n function warnAboutAccessingKey() {\n specialPropKeyWarningShown ||\n ((specialPropKeyWarningShown = !0),\n console.error(\n \"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)\",\n displayName\n ));\n }\n warnAboutAccessingKey.isReactWarning = !0;\n Object.defineProperty(props, \"key\", {\n get: warnAboutAccessingKey,\n configurable: !0\n });\n }\n function elementRefGetterWithDeprecationWarning() {\n var componentName = getComponentNameFromType(this.type);\n didWarnAboutElementRef[componentName] ||\n ((didWarnAboutElementRef[componentName] = !0),\n console.error(\n \"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.\"\n ));\n componentName = this.props.ref;\n return void 0 !== componentName ? componentName : null;\n }\n function ReactElement(\n type,\n key,\n self,\n source,\n owner,\n props,\n debugStack,\n debugTask\n ) {\n self = props.ref;\n type = {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n props: props,\n _owner: owner\n };\n null !== (void 0 !== self ? self : null)\n ? Object.defineProperty(type, \"ref\", {\n enumerable: !1,\n get: elementRefGetterWithDeprecationWarning\n })\n : Object.defineProperty(type, \"ref\", { enumerable: !1, value: null });\n type._store = {};\n Object.defineProperty(type._store, \"validated\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: 0\n });\n Object.defineProperty(type, \"_debugInfo\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: null\n });\n Object.defineProperty(type, \"_debugStack\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugStack\n });\n Object.defineProperty(type, \"_debugTask\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugTask\n });\n Object.freeze && (Object.freeze(type.props), Object.freeze(type));\n return type;\n }\n function jsxDEVImpl(\n type,\n config,\n maybeKey,\n isStaticChildren,\n source,\n self,\n debugStack,\n debugTask\n ) {\n var children = config.children;\n if (void 0 !== children)\n if (isStaticChildren)\n if (isArrayImpl(children)) {\n for (\n isStaticChildren = 0;\n isStaticChildren < children.length;\n isStaticChildren++\n )\n validateChildKeys(children[isStaticChildren]);\n Object.freeze && Object.freeze(children);\n } else\n console.error(\n \"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.\"\n );\n else validateChildKeys(children);\n if (hasOwnProperty.call(config, \"key\")) {\n children = getComponentNameFromType(type);\n var keys = Object.keys(config).filter(function (k) {\n return \"key\" !== k;\n });\n isStaticChildren =\n 0 < keys.length\n ? \"{key: someKey, \" + keys.join(\": ..., \") + \": ...}\"\n : \"{key: someKey}\";\n didWarnAboutKeySpread[children + isStaticChildren] ||\n ((keys =\n 0 < keys.length ? \"{\" + keys.join(\": ..., \") + \": ...}\" : \"{}\"),\n console.error(\n 'A props object containing a \"key\" prop is being spread into JSX:\\n let props = %s;\\n <%s {...props} />\\nReact keys must be passed directly to JSX without using spread:\\n let props = %s;\\n <%s key={someKey} {...props} />',\n isStaticChildren,\n children,\n keys,\n children\n ),\n (didWarnAboutKeySpread[children + isStaticChildren] = !0));\n }\n children = null;\n void 0 !== maybeKey &&\n (checkKeyStringCoercion(maybeKey), (children = \"\" + maybeKey));\n hasValidKey(config) &&\n (checkKeyStringCoercion(config.key), (children = \"\" + config.key));\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n children &&\n defineKeyPropWarningGetter(\n maybeKey,\n \"function\" === typeof type\n ? type.displayName || type.name || \"Unknown\"\n : type\n );\n return ReactElement(\n type,\n children,\n self,\n source,\n getOwner(),\n maybeKey,\n debugStack,\n debugTask\n );\n }\n function validateChildKeys(node) {\n \"object\" === typeof node &&\n null !== node &&\n node.$$typeof === REACT_ELEMENT_TYPE &&\n node._store &&\n (node._store.validated = 1);\n }\n var React = require(\"react\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\");\n Symbol.for(\"react.provider\");\n var REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\"),\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n hasOwnProperty = Object.prototype.hasOwnProperty,\n isArrayImpl = Array.isArray,\n createTask = console.createTask\n ? console.createTask\n : function () {\n return null;\n };\n React = {\n react_stack_bottom_frame: function (callStackForError) {\n return callStackForError();\n }\n };\n var specialPropKeyWarningShown;\n var didWarnAboutElementRef = {};\n var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(\n React,\n UnknownOwner\n )();\n var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));\n var didWarnAboutKeySpread = {};\n exports.Fragment = REACT_FRAGMENT_TYPE;\n exports.jsx = function (type, config, maybeKey, source, self) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !1,\n source,\n self,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n exports.jsxs = function (type, config, maybeKey, source, self) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !0,\n source,\n self,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n })();\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","/**\n * Provider component that manages the WebSocket connection to the DevTools hub\n * and exposes it to the React tree via {@link HubContext}.\n *\n * @remarks\n * `HubProvider` owns the full connection lifecycle: initial handshake,\n * exponential-backoff reconnection, message fan-out to subscribers, and\n * graceful teardown on unmount. All DevTools UI hooks depend on this\n * provider being present in the ancestor tree.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport {\n DevtoolsRole,\n PROTOCOL_VERSION,\n type DevtoolsMessage,\n type ExtensionCapabilities,\n} from \"@yoltra/devtools-protocol\";\nimport { useCallback, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport type { HubConnectionConfig, HubConnectionStatus, HubContextValue } from \"../types\";\nimport { HubContext } from \"./HubContext\";\n\n/** @internal Default extension capabilities advertised during handshake. */\nconst DEFAULT_CAPABILITIES: ExtensionCapabilities = {\n timeTravel: true,\n eventReplay: true,\n stateExplorer: true,\n eventEmit: true,\n performanceMetrics: true,\n};\n\n/** @internal Base delay (ms) for exponential backoff reconnection. */\nconst RECONNECT_BASE_MS = 750;\n\n/** @internal Maximum delay (ms) cap for exponential backoff reconnection. */\nconst RECONNECT_MAX_MS = 30_000;\n\n/**\n * Provides hub connection context to all child hooks and components.\n *\n * @remarks\n * On mount the provider opens a WebSocket to the hub, performs the protocol\n * handshake, and begins dispatching incoming messages to all subscribers. If\n * the connection drops and `autoReconnect` is enabled (default), it\n * reconnects with exponential backoff up to `maxReconnectAttempts`.\n *\n * @example\n * ```tsx\n * import { HubProvider } from \"@yoltra/devtools-ui\";\n *\n * function App() {\n * return (\n * <HubProvider config={{ port: 8900 }}>\n * <DevToolsPanel />\n * </HubProvider>\n * );\n * }\n * ```\n *\n * @param props.config - Connection configuration (see {@link HubConnectionConfig}).\n * @param props.children - React children that will have access to the hub context.\n * @returns A React element wrapping children in {@link HubContext.Provider}.\n *\n * @public\n */\nexport function HubProvider({\n config,\n children,\n}: {\n config: HubConnectionConfig;\n children: ReactNode;\n}) {\n const [status, setStatus] = useState<HubConnectionStatus>(\"disconnected\");\n const wsRef = useRef<WebSocket | null>(null);\n const subscribersRef = useRef<Set<(msg: DevtoolsMessage) => void>>(new Set());\n const reconnectAttemptRef = useRef(0);\n const reconnectTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const extensionIdRef = useRef(crypto.randomUUID());\n const configRef = useRef(config);\n configRef.current = config;\n\n const connect = useCallback(() => {\n const cfg = configRef.current;\n const host = cfg.host ?? \"localhost\";\n const url = `ws://${host}:${cfg.port}`;\n const WS =\n cfg.WebSocket ??\n (typeof globalThis.WebSocket !== \"undefined\" ? globalThis.WebSocket : undefined);\n\n if (!WS) {\n console.error(\n \"[Yoltra DevTools] No WebSocket implementation available. In Node.js, pass { WebSocket } from 'ws' via config.WebSocket.\",\n );\n return;\n }\n\n setStatus(\"connecting\");\n\n try {\n const ws = new WS(url);\n wsRef.current = ws;\n\n ws.onopen = () => {\n reconnectAttemptRef.current = 0;\n\n const handshake = JSON.stringify({\n type: \"HANDSHAKE_REQUEST\",\n protocolVersion: PROTOCOL_VERSION,\n role: DevtoolsRole.EXTENSION,\n extension: {\n id: extensionIdRef.current,\n name: cfg.extensionName ?? \"DevTools UI\",\n capabilities: DEFAULT_CAPABILITIES,\n },\n });\n ws.send(handshake);\n };\n\n ws.onmessage = (event) => {\n try {\n // Handle both string (browser) and Buffer (Node.js ws package) data\n const raw = typeof event.data === \"string\" ? event.data : String(event.data);\n const msg: DevtoolsMessage = JSON.parse(raw);\n\n if (msg.type === \"HANDSHAKE_RESPONSE\") {\n if (msg.success) {\n setStatus(\"connected\");\n } else {\n ws.close();\n }\n return;\n }\n\n subscribersRef.current.forEach((handler) => handler(msg));\n } catch {\n // Ignore malformed messages\n }\n };\n\n ws.onclose = () => {\n wsRef.current = null;\n setStatus(\"disconnected\");\n\n const autoReconnect = cfg.autoReconnect ?? true;\n const maxAttempts = cfg.maxReconnectAttempts ?? Infinity;\n\n if (autoReconnect && reconnectAttemptRef.current < maxAttempts) {\n const attempt = reconnectAttemptRef.current++;\n const delay = Math.min(\n RECONNECT_BASE_MS * Math.pow(2, attempt) + Math.random() * 500,\n RECONNECT_MAX_MS,\n );\n reconnectTimerRef.current = setTimeout(connect, delay);\n }\n };\n\n ws.onerror = () => {\n // onclose will fire after onerror\n };\n } catch {\n setStatus(\"disconnected\");\n }\n }, []);\n\n const disconnect = useCallback(() => {\n if (reconnectTimerRef.current) {\n clearTimeout(reconnectTimerRef.current);\n reconnectTimerRef.current = null;\n }\n reconnectAttemptRef.current = Infinity; // Prevent auto-reconnect\n wsRef.current?.close();\n wsRef.current = null;\n setStatus(\"disconnected\");\n }, []);\n\n const reconnect = useCallback(() => {\n reconnectAttemptRef.current = 0;\n wsRef.current?.close();\n wsRef.current = null;\n connect();\n }, [connect]);\n\n const send = useCallback((message: DevtoolsMessage) => {\n const ws = wsRef.current;\n if (ws && ws.readyState === 1 /* OPEN */) {\n ws.send(JSON.stringify(message));\n }\n }, []);\n\n const subscribe = useCallback((handler: (msg: DevtoolsMessage) => void) => {\n subscribersRef.current.add(handler);\n return () => {\n subscribersRef.current.delete(handler);\n };\n }, []);\n\n useEffect(() => {\n connect();\n return () => {\n if (reconnectTimerRef.current) {\n clearTimeout(reconnectTimerRef.current);\n }\n reconnectAttemptRef.current = Infinity;\n wsRef.current?.close();\n };\n }, [connect]);\n\n const value: HubContextValue = {\n status,\n send,\n subscribe,\n disconnect,\n reconnect,\n };\n\n return <HubContext.Provider value={value}>{children}</HubContext.Provider>;\n}\n","/**\n * Hook for accessing the DevTools hub connection from any component.\n *\n * @remarks\n * Thin wrapper around `useContext(HubContext)`. It is the primary entry-point\n * for all other DevTools UI hooks that need to send or subscribe to hub\n * messages. Must be rendered inside a {@link HubProvider}.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport { useContext } from \"react\";\nimport { HubContext } from \"../context/HubContext\";\nimport type { HubContextValue } from \"../types\";\n\n/**\n * Access the hub connection context.\n *\n * @remarks\n * Must be used within a {@link HubProvider}. If called outside a provider\n * the returned value contains safe no-op functions and a `\"disconnected\"`\n * status.\n *\n * @example\n * ```tsx\n * import { useHubConnection } from \"@yoltra/devtools-ui\";\n *\n * function ConnectionStatus() {\n * const { status, reconnect } = useHubConnection();\n * return (\n * <div>\n * <span>Status: {status}</span>\n * <button onClick={reconnect}>Reconnect</button>\n * </div>\n * );\n * }\n * ```\n *\n * @returns The hub connection context value (see {@link HubContextValue}).\n *\n * @public\n */\nexport function useHubConnection(): HubContextValue {\n return useContext(HubContext);\n}\n","/**\n * Hook that allows the DevTools extension to emit custom events to a\n * Yoltra store.\n *\n * @remarks\n * Wraps the `EMIT_TO_STORE` protocol message. The emitted event is\n * dispatched through the store's normal event pipeline (middleware,\n * reducers, subscribers) just as if it had been emitted from application\n * code. This is useful for manually triggering state transitions during\n * debugging.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport { DevtoolsRole } from \"@yoltra/devtools-protocol\";\nimport { useCallback } from \"react\";\nimport { useHubConnection } from \"./useHubConnection\";\n\n/**\n * Emits events to a store from the extension.\n *\n * @remarks\n * The returned `emit` function is referentially stable (memoised via\n * `useCallback`) and safe to include in dependency arrays. Calling `emit`\n * when `storeId` is `null` is a no-op.\n *\n * @example\n * ```tsx\n * import { useEventEmitter } from \"@yoltra/devtools-ui\";\n *\n * function EmitForm({ storeId }: { storeId: string }) {\n * const { emit } = useEventEmitter(storeId);\n *\n * const handleClick = () => {\n * emit(\"counter\", \"INCREMENT\", { amount: 1 });\n * };\n *\n * return <button onClick={handleClick}>Increment Counter</button>;\n * }\n * ```\n *\n * @param storeId - The store ID to emit events to, or `null` to disable.\n * @returns An object containing the `emit(channel, type, payload)` function.\n *\n * @public\n */\nexport function useEventEmitter(storeId: string | null): {\n emit: (channel: string, type: string, payload: unknown) => void;\n} {\n const { send } = useHubConnection();\n\n const emit = useCallback(\n (channel: string, type: string, payload: unknown) => {\n if (!storeId) return;\n\n send({\n type: \"EMIT_TO_STORE\",\n storeId,\n event: { channel, type, payload },\n timestamp: new Date().toISOString(),\n sourceId: \"\",\n sourceRole: DevtoolsRole.EXTENSION,\n });\n },\n [storeId, send],\n );\n\n return { emit };\n}\n","/**\n * Hook that accumulates a chronological log of store events for inspection.\n *\n * @remarks\n * Subscribes to `STORE_EVENT` messages for **all** stores and stores them in\n * a per-store map so that history is retained when the user switches between\n * store tabs. The `storeId` parameter controls which store's slice is\n * returned, but collection is never paused or reset when the selected store\n * changes.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport type { DevtoolsMessage } from \"@yoltra/devtools-protocol\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { EventLogEntry } from \"../types\";\nimport { useHubConnection } from \"./useHubConnection\";\n\n/** @internal Default upper bound on retained event log entries per store. */\nconst DEFAULT_MAX_ENTRIES = 2000;\n\n/**\n * Options for the {@link useEventLog} hook.\n *\n * @public\n */\nexport interface UseEventLogOptions {\n /** Maximum number of entries to keep per store. @defaultValue `2000` */\n maxEntries?: number;\n}\n\n/**\n * Maintains a chronological event log for a given store.\n *\n * @remarks\n * Events are accumulated for **all** stores simultaneously in a `Map` keyed\n * by store ID, so switching between store tabs does not discard existing\n * history. Passing `null` as `storeId` returns an empty array but collection\n * continues in the background.\n *\n * When the log for a given store exceeds `maxEntries` the oldest entries for\n * that store are discarded.\n *\n * @example\n * ```tsx\n * import { useEventLog } from \"@yoltra/devtools-ui\";\n *\n * function EventTimeline({ storeId }: { storeId: string }) {\n * const { entries, clear } = useEventLog(storeId, { maxEntries: 500 });\n * return (\n * <div>\n * <button onClick={clear}>Clear</button>\n * <ul>\n * {entries.map((e, i) => (\n * <li key={i}>{e.event.type} @ {e.timestamp}</li>\n * ))}\n * </ul>\n * </div>\n * );\n * }\n * ```\n *\n * @param storeId - The store ID whose events to return, or `null` to get an\n * empty slice (collection still runs for all stores).\n * @param options - Optional configuration (see {@link UseEventLogOptions}).\n * @returns An object containing the `entries` array and a `clear` function.\n *\n * @public\n */\nexport function useEventLog(\n storeId: string | null,\n options?: UseEventLogOptions,\n): { entries: EventLogEntry[]; clear: () => void } {\n const { subscribe } = useHubConnection();\n const maxEntries = options?.maxEntries ?? DEFAULT_MAX_ENTRIES;\n\n /**\n * Per-store event log, keyed by storeId.\n * Stored in a ref so mutations don't trigger unnecessary re-renders; we\n * control re-renders manually via the `tick` counter below.\n */\n const allEntriesRef = useRef<Map<string, EventLogEntry[]>>(new Map());\n const maxRef = useRef(maxEntries);\n maxRef.current = maxEntries;\n\n /**\n * Incremented on every mutation to trigger a re-render so consumers see\n * the latest entries. The value itself is not used in the render output.\n */\n const [, setTick] = useState(0);\n\n useEffect(() => {\n // Subscribe once for the lifetime of the provider — collect events for\n // ALL stores so history persists regardless of which store tab is active.\n const unsub = subscribe((msg: DevtoolsMessage) => {\n if (msg.type !== \"STORE_EVENT\") return;\n\n const sid = msg.storeId;\n const entry: EventLogEntry = {\n event: msg.event,\n storeId: sid,\n patches: msg.patches,\n snapshotVersion: msg.snapshotVersion,\n committed: msg.committed,\n timestamp: msg.timestamp,\n };\n\n const prev = allEntriesRef.current.get(sid) ?? [];\n const next = [...prev, entry];\n allEntriesRef.current.set(\n sid,\n next.length > maxRef.current ? next.slice(next.length - maxRef.current) : next,\n );\n\n setTick((t) => t + 1);\n });\n\n return unsub;\n // subscribe is stable for the lifetime of HubProvider — intentionally\n // omit storeId so the subscription is never restarted on tab switch.\n }, [subscribe]);\n\n /** Clear the event log for the currently selected store only. */\n const clear = useCallback(() => {\n if (storeId) {\n allEntriesRef.current.delete(storeId);\n setTick((t) => t + 1);\n }\n }, [storeId]);\n\n const entries = storeId ? (allEntriesRef.current.get(storeId) ?? []) : [];\n\n return { entries, clear };\n}\n","/**\n * Hook that replays a sequence of events through a store's reducer pipeline\n * starting from a given snapshot.\n *\n * @remarks\n * Sends an `EVENT_REPLAY` message to the hub containing the base snapshot\n * and the ordered list of events to replay. The store re-processes each\n * event through its reducers and updates its state accordingly. This is\n * useful for \"what-if\" analysis and debugging reducer logic.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport { DevtoolsRole } from \"@yoltra/devtools-protocol\";\nimport { useCallback } from \"react\";\nimport type { EventLogEntry } from \"../types\";\nimport { useHubConnection } from \"./useHubConnection\";\n\n/**\n * Replays events through a store's reducers from a given snapshot.\n *\n * @remarks\n * The `replay` function accepts a base state snapshot and an array of\n * {@link EventLogEntry} objects. It serialises the events into the protocol\n * format and sends a single `EVENT_REPLAY` message to the hub. The store\n * is expected to process each event sequentially through its reducer\n * pipeline and emit the resulting state.\n *\n * @example\n * ```tsx\n * import { useEventLog, useStoreState, useEventReplay } from \"@yoltra/devtools-ui\";\n *\n * function ReplayButton({ storeId }: { storeId: string }) {\n * const { state } = useStoreState(storeId);\n * const { entries } = useEventLog(storeId);\n * const { replay } = useEventReplay(storeId);\n *\n * return (\n * <button onClick={() => replay(state, entries)}>\n * Replay All Events\n * </button>\n * );\n * }\n * ```\n *\n * @param storeId - The store ID to replay events on, or `null` to disable.\n * @returns An object containing the `replay` function.\n *\n * @public\n */\nexport function useEventReplay(storeId: string | null): {\n replay: (snapshot: unknown, events: EventLogEntry[]) => void;\n} {\n const { send } = useHubConnection();\n\n const replay = useCallback(\n (snapshot: unknown, events: EventLogEntry[]) => {\n if (!storeId) return;\n\n send({\n type: \"EVENT_REPLAY\",\n storeId,\n snapshot,\n events: events.map((e) => ({\n id: e.event.id,\n channel: e.event.channel,\n type: e.event.type,\n payload: e.event.payload,\n })),\n timestamp: new Date().toISOString(),\n sourceId: \"\",\n sourceRole: DevtoolsRole.EXTENSION,\n });\n },\n [storeId, send],\n );\n\n return { replay };\n}\n","/**\n * Hook that fetches and auto-refreshes performance metrics for a Yoltra store.\n *\n * @remarks\n * Sends periodic `REQUEST_METRICS` messages to the hub and caches the\n * latest `STORE_METRICS` response. The polling interval is configurable\n * and can be disabled by setting `refreshIntervalMs` to `0`.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport {\n DevtoolsRole,\n type DevtoolsMessage,\n type StoreMetrics,\n} from \"@yoltra/devtools-protocol\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useHubConnection } from \"./useHubConnection\";\n\n/**\n * Metrics payload extracted from a `STORE_METRICS` message.\n *\n * @internal\n */\ntype MetricsData = StoreMetrics[\"metrics\"];\n\n/**\n * Options for the {@link useStoreMetrics} hook.\n *\n * @public\n */\nexport interface UseStoreMetricsOptions {\n /** Auto-refresh interval in milliseconds. Set to `0` to disable. @defaultValue `2000` */\n refreshIntervalMs?: number;\n}\n\n/**\n * Fetches and caches performance metrics for a store, with automatic\n * periodic refresh.\n *\n * @remarks\n * On mount the hook immediately requests metrics and starts an interval\n * timer that re-fetches every `refreshIntervalMs` milliseconds (default\n * 2 000). The timer is cleaned up on unmount or when the `storeId` changes.\n *\n * @example\n * ```tsx\n * import { useStoreMetrics } from \"@yoltra/devtools-ui\";\n *\n * function MetricsPanel({ storeId }: { storeId: string }) {\n * const { metrics, loading, refresh } = useStoreMetrics(storeId, {\n * refreshIntervalMs: 5000,\n * });\n * if (loading || !metrics) return <p>Loading...</p>;\n * return (\n * <div>\n * <pre>{JSON.stringify(metrics, null, 2)}</pre>\n * <button onClick={refresh}>Refresh Now</button>\n * </div>\n * );\n * }\n * ```\n *\n * @param storeId - The store ID to query, or `null` to disable.\n * @param options - Optional configuration (see {@link UseStoreMetricsOptions}).\n * @returns An object with `metrics` ({@link MetricsData} or `null`),\n * `loading`, and `refresh`.\n *\n * @public\n */\nexport function useStoreMetrics(\n storeId: string | null,\n options?: UseStoreMetricsOptions,\n): {\n metrics: MetricsData | null;\n loading: boolean;\n refresh: () => void;\n} {\n const { send, subscribe } = useHubConnection();\n const [metrics, setMetrics] = useState<MetricsData | null>(null);\n const [loading, setLoading] = useState(false);\n const intervalMs = options?.refreshIntervalMs ?? 2000;\n const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n const requestMetrics = useCallback(() => {\n if (!storeId) return;\n setLoading(true);\n send({\n type: \"REQUEST_METRICS\",\n storeId,\n timestamp: new Date().toISOString(),\n sourceId: \"\",\n sourceRole: DevtoolsRole.EXTENSION,\n });\n }, [storeId, send]);\n\n useEffect(() => {\n if (!storeId) {\n setMetrics(null);\n return;\n }\n\n requestMetrics();\n\n const unsub = subscribe((msg: DevtoolsMessage) => {\n if (msg.type === \"STORE_METRICS\" && msg.storeId === storeId) {\n setMetrics(msg.metrics);\n setLoading(false);\n }\n });\n\n // Auto-refresh\n if (intervalMs > 0) {\n timerRef.current = setInterval(requestMetrics, intervalMs);\n }\n\n return () => {\n unsub();\n if (timerRef.current) {\n clearInterval(timerRef.current);\n timerRef.current = null;\n }\n };\n }, [storeId, subscribe, requestMetrics, intervalMs]);\n\n return { metrics, loading, refresh: requestMetrics };\n}\n","/**\n * Hook that maintains a live list of stores registered with the DevTools hub.\n *\n * @remarks\n * Subscribes to `STORE_REGISTRY`, `STORE_CONNECTED`, and\n * `STORE_DISCONNECTED` hub messages and keeps an up-to-date array of\n * {@link RegisteredStore} entries. Use this to build store selector UIs.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport type { DevtoolsMessage } from \"@yoltra/devtools-protocol\";\nimport { useEffect, useState } from \"react\";\nimport type { RegisteredStore } from \"../types\";\nimport { useHubConnection } from \"./useHubConnection\";\n\n/**\n * Tracks connected stores from `STORE_REGISTRY` hub broadcasts.\n *\n * @remarks\n * The hook listens for three message types:\n * - `STORE_REGISTRY` -- replaces the full store list (sent on initial connect).\n * - `STORE_CONNECTED` -- adds or updates a single store entry.\n * - `STORE_DISCONNECTED` -- marks a store as `\"disconnected\"`.\n *\n * The returned array is referentially stable unless the underlying data changes.\n *\n * @example\n * ```tsx\n * import { useStoreRegistry } from \"@yoltra/devtools-ui\";\n *\n * function StoreList() {\n * const stores = useStoreRegistry();\n * return (\n * <ul>\n * {stores.map((s) => (\n * <li key={s.id}>{s.name} ({s.status})</li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n *\n * @returns The current list of registered stores (see {@link RegisteredStore}).\n *\n * @public\n */\nexport function useStoreRegistry(): RegisteredStore[] {\n const { subscribe } = useHubConnection();\n const [stores, setStores] = useState<RegisteredStore[]>([]);\n\n useEffect(() => {\n const unsub = subscribe((msg: DevtoolsMessage) => {\n switch (msg.type) {\n case \"STORE_REGISTRY\":\n setStores(msg.stores);\n break;\n case \"STORE_CONNECTED\":\n setStores((prev) => {\n const exists = prev.some((s) => s.id === msg.store.id);\n if (exists) {\n return prev.map((s) =>\n s.id === msg.store.id ? { ...s, status: \"connected\" as const } : s,\n );\n }\n return [\n ...prev,\n {\n id: msg.store.id,\n name: msg.store.name,\n status: \"connected\" as const,\n capabilities: msg.store.capabilities,\n connectedAt: msg.timestamp,\n },\n ];\n });\n break;\n case \"STORE_DISCONNECTED\":\n setStores((prev) =>\n prev.map((s) =>\n s.id === msg.storeId ? { ...s, status: \"disconnected\" as const } : s,\n ),\n );\n break;\n }\n });\n return unsub;\n }, [subscribe]);\n\n return stores;\n}\n","/**\n * Immutable RFC 6902 JSON Patch utility used by the DevTools UI state hooks.\n *\n * @remarks\n * This module provides a minimal, dependency-free implementation of the\n * `add`, `remove`, and `replace` JSON Patch operations. It is used\n * internally by {@link useStoreState} to apply incremental state patches\n * received from the hub without mutating the existing state tree.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport type { JsonPatch } from \"@yoltra/devtools-protocol\";\n\n/**\n * Apply an array of RFC 6902 JSON Patch operations to a value.\n * Returns a new object -- does not mutate the input.\n *\n * @remarks\n * Only the `add`, `remove`, and `replace` operations are implemented because\n * the v1 devtools protocol does not emit `move`, `copy`, or `test` patches.\n * Each operation is applied sequentially in array order. Path segments are\n * resolved according to RFC 6901 (JSON Pointer), including `~0` / `~1`\n * escape handling.\n *\n * @example\n * ```ts\n * import { applyPatches } from \"@yoltra/devtools-ui\";\n *\n * const next = applyPatches(\n * { counter: { value: 0 } },\n * [{ op: \"replace\", path: \"/counter/value\", value: 1 }],\n * );\n * // next => { counter: { value: 1 } }\n * ```\n *\n * @param target - The value to patch.\n * @param patches - RFC 6902 operations.\n * @returns A new patched value.\n *\n * @public\n */\nexport function applyPatches<T = unknown>(target: T, patches: JsonPatch[]): T {\n let result: any = structuredClone(target);\n\n for (const patch of patches) {\n const segments = parsePointer(patch.path);\n switch (patch.op) {\n case \"add\":\n // RFC 6902 `add` inserts into arrays (replace only for objects); `replace`\n // always overwrites. Threading the op keeps array indices correct.\n result = setAtPath(result, segments, patch.value, true);\n break;\n case \"replace\":\n result = setAtPath(result, segments, patch.value, false);\n break;\n case \"remove\":\n result = removeAtPath(result, segments);\n break;\n // move, copy, test — not used in v1 protocol\n }\n }\n\n return result;\n}\n\n/**\n * Parse a JSON Pointer (RFC 6901) into path segments.\n *\n * @remarks\n * Handles `~0` and `~1` escape sequences as specified by RFC 6901.\n * E.g., `\"/counter/value\"` becomes `[\"counter\", \"value\"]`.\n *\n * @param pointer - A JSON Pointer string (e.g. `\"/a/b/c\"`).\n * @returns An array of unescaped path segments.\n *\n * @internal\n */\nfunction parsePointer(pointer: string): string[] {\n if (pointer === \"\" || pointer === \"/\") return [];\n return pointer\n .slice(1) // Remove leading \"/\"\n .split(\"/\")\n .map((s) => s.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n}\n\n/**\n * Immutably set a value at the given path segments within an object or array.\n *\n * @param obj - The root object.\n * @param segments - Path segments produced by {@link parsePointer}.\n * @param value - The value to set.\n * @returns A shallow-cloned tree with the value set.\n *\n * @internal\n */\n/**\n * Keys that must never be written from a JSON Pointer: assigning them walks the\n * prototype chain and pollutes `Object.prototype`. Patch contents originate from\n * a (possibly untrusted) peer store or hub, so the pointer is attacker-chosen.\n */\nconst FORBIDDEN_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nfunction setAtPath(obj: any, segments: string[], value: unknown, insert: boolean): any {\n if (segments.length === 0) return value;\n\n const result = Array.isArray(obj) ? [...obj] : { ...obj };\n const [head, ...rest] = segments;\n\n // Prevent prototype pollution — ignore dangerous segments entirely.\n if (FORBIDDEN_KEYS.has(head)) return result;\n\n if (rest.length === 0) {\n if (insert && Array.isArray(result)) {\n // RFC 6902 `add` on an array: insert before `head` (shifting), or append\n // when `head` is the \"-\" end-of-array token.\n const index = head === \"-\" ? result.length : Number(head);\n if (Number.isInteger(index) && index >= 0 && index <= result.length) {\n result.splice(index, 0, value);\n } else {\n (result as any)[head] = value; // out-of-range / non-numeric: best-effort set\n }\n } else {\n result[head] = value;\n }\n } else {\n result[head] = setAtPath(result[head] ?? {}, rest, value, insert);\n }\n\n return result;\n}\n\n/**\n * Immutably remove the value at the given path segments within an object or array.\n *\n * @param obj - The root object.\n * @param segments - Path segments produced by {@link parsePointer}.\n * @returns A shallow-cloned tree with the value removed.\n *\n * @internal\n */\nfunction removeAtPath(obj: any, segments: string[]): any {\n if (segments.length === 0) return undefined;\n\n const result = Array.isArray(obj) ? [...obj] : { ...obj };\n const [head, ...rest] = segments;\n\n // Prevent prototype-chain traversal from attacker-controlled pointers.\n if (FORBIDDEN_KEYS.has(head)) return result;\n\n if (rest.length === 0) {\n if (Array.isArray(result)) {\n result.splice(Number(head), 1);\n } else {\n delete result[head];\n }\n } else {\n result[head] = removeAtPath(result[head], rest);\n }\n\n return result;\n}\n","/**\n * Framework-agnostic retry policy for one-shot request/response exchanges.\n *\n * @remarks\n * Some DevTools requests (e.g. `REQUEST_STATE`) expect a single response. If\n * that request races store registration or the hub handshake it can be\n * dropped, leaving the UI waiting forever. This helper re-issues the request\n * on a fixed interval until the response is observed, then stops. Extracted\n * from the hooks so the timing behaviour is unit-testable without React.\n *\n * @module @yoltra/devtools-ui\n */\n\n/**\n * Minimal timer surface, injectable so tests can drive it with fake timers.\n *\n * @internal\n */\nexport interface RetryScheduler {\n setInterval: (handler: () => void, ms: number) => ReturnType<typeof setInterval>;\n clearInterval: (id: ReturnType<typeof setInterval>) => void;\n}\n\n/**\n * Options for {@link startSnapshotRetry}.\n *\n * @internal\n */\nexport interface SnapshotRetryOptions {\n /** Re-issue the request. Called once per interval until settled. */\n request: () => void;\n /** Returns `true` once the awaited response has been observed. */\n isSettled: () => boolean;\n /** Interval between retries, in milliseconds. */\n intervalMs: number;\n /** Timer implementation. Defaults to the global timers. */\n scheduler?: RetryScheduler;\n}\n\n/**\n * Begin re-issuing `request` every `intervalMs` until `isSettled()` returns\n * `true`, at which point the retry stops on its own. Returns a cancel function\n * that stops it immediately (call on unmount / when the response arrives).\n *\n * @param options - See {@link SnapshotRetryOptions}.\n * @returns A function that cancels the retry loop.\n * @internal\n */\nexport function startSnapshotRetry(options: SnapshotRetryOptions): () => void {\n const scheduler: RetryScheduler = options.scheduler ?? {\n setInterval: (h, ms) => setInterval(h, ms),\n clearInterval: (id) => clearInterval(id),\n };\n\n let id: ReturnType<typeof setInterval> | null = scheduler.setInterval(() => {\n if (options.isSettled()) {\n cancel();\n return;\n }\n options.request();\n }, options.intervalMs);\n\n function cancel() {\n if (id !== null) {\n scheduler.clearInterval(id);\n id = null;\n }\n }\n\n return cancel;\n}\n","/**\n * Hook that provides a live, incrementally-patched view of a store's state.\n *\n * @remarks\n * On activation, the hook requests a full `STATE_SNAPSHOT` from the hub.\n * While waiting, any `STORE_EVENT` patches that arrive are buffered and\n * replayed once the snapshot lands. After that, each committed patch is\n * applied via {@link applyPatches} so the UI always reflects the latest\n * store state without requiring full snapshots.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport { DevtoolsRole, type DevtoolsMessage, type JsonPatch } from \"@yoltra/devtools-protocol\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { applyPatches } from \"../utils/apply-patch\";\nimport { startSnapshotRetry } from \"./snapshotRetry\";\nimport { useHubConnection } from \"./useHubConnection\";\n\n/**\n * How often to re-send `REQUEST_STATE` until the first `STATE_SNAPSHOT`\n * arrives. A single request can be lost if it races store registration or\n * the hub handshake, which would otherwise hang the panel forever; retrying\n * until the baseline lands makes the State view self-heal.\n *\n * @internal\n */\nconst SNAPSHOT_RETRY_INTERVAL_MS = 1500;\n\n/**\n * Lazily fetches a store's full state and keeps it up-to-date via patches.\n *\n * @remarks\n * The state is initially `null` until a `STATE_SNAPSHOT` is received.\n * After that, incoming `STORE_EVENT` patches are applied incrementally\n * using {@link applyPatches}. Patches that arrive before the snapshot are\n * buffered and replayed in version order once the snapshot is available.\n *\n * Call `refresh()` to discard the current state and re-fetch from scratch.\n *\n * @example\n * ```tsx\n * import { useStoreState } from \"@yoltra/devtools-ui\";\n *\n * function StateInspector({ storeId }: { storeId: string }) {\n * const { state, version, loading, refresh } = useStoreState(storeId);\n * if (loading) return <p>Loading...</p>;\n * return (\n * <div>\n * <p>Version: {version}</p>\n * <pre>{JSON.stringify(state, null, 2)}</pre>\n * <button onClick={refresh}>Refresh</button>\n * </div>\n * );\n * }\n * ```\n *\n * @param storeId - The store ID to track state for, or `null` to disable.\n * @returns An object with `state`, `version`, `loading`, and `refresh`.\n *\n * @public\n */\nexport function useStoreState(storeId: string | null): {\n state: unknown;\n version: number;\n loading: boolean;\n refresh: () => void;\n} {\n const { send, subscribe } = useHubConnection();\n const [state, setState] = useState<unknown>(null);\n const [version, setVersion] = useState(0);\n const [loading, setLoading] = useState(false);\n const versionRef = useRef(0);\n const pendingPatchesRef = useRef<Array<{ patches: JsonPatch[]; version: number }>>([]);\n const cancelRetryRef = useRef<(() => void) | null>(null);\n\n const stopRetry = useCallback(() => {\n cancelRetryRef.current?.();\n cancelRetryRef.current = null;\n }, []);\n\n const requestState = useCallback(() => {\n if (!storeId) return;\n setLoading(true);\n send({\n type: \"REQUEST_STATE\",\n storeId,\n timestamp: new Date().toISOString(),\n sourceId: \"\",\n sourceRole: DevtoolsRole.EXTENSION,\n });\n }, [storeId, send]);\n\n useEffect(() => {\n if (!storeId) {\n setState(null);\n setVersion(0);\n versionRef.current = 0;\n return;\n }\n\n requestState();\n\n // Keep re-requesting until the first snapshot lands. A single REQUEST_STATE\n // can be dropped if it races store registration / the handshake, which used\n // to hang the State (and time-travel baseline) view indefinitely. The\n // snapshot handler below cancels this the moment a snapshot arrives.\n cancelRetryRef.current = startSnapshotRetry({\n request: requestState,\n isSettled: () => versionRef.current !== 0,\n intervalMs: SNAPSHOT_RETRY_INTERVAL_MS,\n });\n\n const unsub = subscribe((msg: DevtoolsMessage) => {\n if (msg.type === \"STATE_SNAPSHOT\" && msg.storeId === storeId) {\n stopRetry();\n setState(msg.state);\n setVersion(msg.version);\n versionRef.current = msg.version;\n setLoading(false);\n\n // Apply any buffered patches that arrived after the snapshot version\n const pending = pendingPatchesRef.current\n .filter((p) => p.version > msg.version)\n .sort((a, b) => a.version - b.version);\n pendingPatchesRef.current = [];\n\n if (pending.length > 0) {\n setState((prev: any) => {\n let current = prev;\n for (const p of pending) {\n current = applyPatches(current, p.patches);\n }\n return current;\n });\n const lastVersion = pending[pending.length - 1].version;\n setVersion(lastVersion);\n versionRef.current = lastVersion;\n }\n return;\n }\n\n if (msg.type === \"STORE_EVENT\" && msg.storeId === storeId && msg.committed) {\n if (versionRef.current === 0) {\n // No snapshot yet — buffer patches\n pendingPatchesRef.current.push({\n patches: msg.patches,\n version: msg.snapshotVersion,\n });\n return;\n }\n\n if (msg.snapshotVersion <= versionRef.current) {\n // Already applied\n return;\n }\n\n setState((prev: any) => applyPatches(prev, msg.patches));\n setVersion(msg.snapshotVersion);\n versionRef.current = msg.snapshotVersion;\n }\n });\n\n return () => {\n unsub();\n stopRetry();\n pendingPatchesRef.current = [];\n };\n }, [storeId, subscribe, requestState, stopRetry]);\n\n return { state, version, loading, refresh: requestState };\n}\n","/**\n * Hook that fetches and caches subscription and consumer information for\n * a Yoltra store.\n *\n * @remarks\n * Sends a `REQUEST_SUBSCRIPTIONS` message to the hub and resolves when\n * the corresponding `STORE_SUBSCRIPTIONS` response arrives. The result\n * includes atomic, event, coarse, effect, middleware, and reducer\n * subscription breakdowns. Call `refresh()` to re-fetch.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport {\n DevtoolsRole,\n type DevtoolsMessage,\n type StoreSubscriptions,\n} from \"@yoltra/devtools-protocol\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useHubConnection } from \"./useHubConnection\";\n\n/**\n * Subscription data payload with protocol envelope fields stripped.\n *\n * @internal\n */\ntype SubscriptionData = Omit<\n StoreSubscriptions,\n \"type\" | \"timestamp\" | \"sourceId\" | \"sourceRole\" | \"storeId\"\n>;\n\n/**\n * Fetches and caches subscription/consumer info for a store.\n *\n * @remarks\n * On mount (or when `storeId` changes) the hook sends a\n * `REQUEST_SUBSCRIPTIONS` message and sets `loading` to `true`. When the\n * matching `STORE_SUBSCRIPTIONS` response arrives the data is cached and\n * `loading` flips to `false`.\n *\n * @example\n * ```tsx\n * import { useStoreSubscriptions } from \"@yoltra/devtools-ui\";\n *\n * function SubscriptionPanel({ storeId }: { storeId: string }) {\n * const { data, loading, refresh } = useStoreSubscriptions(storeId);\n * if (loading || !data) return <p>Loading...</p>;\n * return (\n * <div>\n * <p>Atomic: {data.atomic.length}</p>\n * <p>Event: {data.event.length}</p>\n * <button onClick={refresh}>Refresh</button>\n * </div>\n * );\n * }\n * ```\n *\n * @param storeId - The store ID to query, or `null` to disable.\n * @returns An object with `data` ({@link SubscriptionData} or `null`),\n * `loading`, and `refresh`.\n *\n * @public\n */\nexport function useStoreSubscriptions(storeId: string | null): {\n data: SubscriptionData | null;\n loading: boolean;\n refresh: () => void;\n} {\n const { send, subscribe } = useHubConnection();\n const [data, setData] = useState<SubscriptionData | null>(null);\n const [loading, setLoading] = useState(false);\n\n const requestSubscriptions = useCallback(() => {\n if (!storeId) return;\n setLoading(true);\n send({\n type: \"REQUEST_SUBSCRIPTIONS\",\n storeId,\n timestamp: new Date().toISOString(),\n sourceId: \"\",\n sourceRole: DevtoolsRole.EXTENSION,\n });\n }, [storeId, send]);\n\n useEffect(() => {\n if (!storeId) {\n setData(null);\n return;\n }\n\n requestSubscriptions();\n\n const unsub = subscribe((msg: DevtoolsMessage) => {\n if (msg.type === \"STORE_SUBSCRIPTIONS\" && msg.storeId === storeId) {\n setData({\n atomic: msg.atomic,\n event: msg.event,\n coarse: msg.coarse,\n effects: msg.effects,\n middleware: msg.middleware,\n reducers: msg.reducers,\n });\n setLoading(false);\n }\n });\n\n return unsub;\n }, [storeId, subscribe, requestSubscriptions]);\n\n return { data, loading, refresh: requestSubscriptions };\n}\n","/**\n * Pure navigation math for time-travel stepping.\n *\n * @remarks\n * Kept separate from {@link useTimeTravel} so the boundary conditions — the\n * part that is easy to get wrong — are unit-testable without React. The hook\n * translates the returned action into `jumpTo` / `resume` calls.\n *\n * @module @yoltra/devtools-ui\n */\n\n/**\n * The action a step resolves to.\n *\n * @internal\n */\nexport type StepAction =\n | { kind: \"jump\"; index: number }\n | { kind: \"resume\" }\n | { kind: \"none\" };\n\n/**\n * Current navigation state.\n *\n * @internal\n */\nexport interface StepState {\n /** Whether a time-travel session is active. */\n isTimeTraveling: boolean;\n /** The viewed entry index while traveling (ignored when not). */\n currentIndex: number;\n /** Total number of recorded events. */\n entryCount: number;\n}\n\n/**\n * Resolve one `back` / `forward` step to a concrete action.\n *\n * - **back** — from live, start at the newest event; while traveling, move\n * relative to the current position. Steps to the previous event, or does\n * nothing at the very start.\n * - **forward** — only meaningful while traveling (nothing lies past live).\n * Advances one event, or resumes the live stream once the newest event is\n * reached so the store is resynced rather than left on a stale snapshot.\n *\n * @param direction - `\"back\"` or `\"forward\"`.\n * @param state - See {@link StepState}.\n * @returns The {@link StepAction} to apply.\n * @internal\n */\nexport function planStep(direction: \"back\" | \"forward\", state: StepState): StepAction {\n const { isTimeTraveling, currentIndex, entryCount } = state;\n const lastIndex = entryCount - 1;\n\n if (direction === \"back\") {\n const viewIndex = isTimeTraveling ? currentIndex : lastIndex;\n const target = viewIndex - 1;\n return target >= 0 ? { kind: \"jump\", index: target } : { kind: \"none\" };\n }\n\n // forward\n if (!isTimeTraveling) return { kind: \"none\" };\n const target = currentIndex + 1;\n // Step onto the newest event; only stepping *past* it returns to live so the\n // store is resynced rather than left on a stale reconstructed snapshot.\n return target > lastIndex ? { kind: \"resume\" } : { kind: \"jump\", index: target };\n}\n","/**\n * Hook that enables time-travel debugging by navigating through an event log\n * and sending `TIME_TRAVEL` commands to a Yoltra store.\n *\n * @remarks\n * Works in concert with {@link useEventLog} -- pass its `entries` array to\n * this hook. Jumping to a specific index sends a `TIME_TRAVEL` message with\n * the corresponding snapshot version so the store can restore that point in\n * time. Call `resume()` to return to live state.\n *\n * @module @yoltra/devtools-ui\n */\n\nimport { DevtoolsRole, type DevtoolsMessage } from \"@yoltra/devtools-protocol\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { EventLogEntry } from \"../types\";\nimport { applyPatches } from \"../utils/apply-patch\";\nimport { planStep } from \"./timeTravelNav\";\nimport { useHubConnection } from \"./useHubConnection\";\n\n/**\n * Provides time-travel navigation through the event log.\n *\n * @remarks\n * The hook tracks whether the user is actively time-traveling via\n * `isTimeTraveling`. While traveling, `currentIndex` indicates the position\n * within the `entries` array. The `stepBack` / `stepForward` helpers move\n * one entry at a time, while `jumpTo` allows arbitrary positioning. Calling\n * `resume()` exits time-travel mode, jumps to the latest entry, and resets\n * the index to `-1`.\n *\n * @example\n * ```tsx\n * import { useEventLog, useTimeTravel } from \"@yoltra/devtools-ui\";\n *\n * function TimeTravelControls({ storeId }: { storeId: string }) {\n * const { entries } = useEventLog(storeId);\n * const { currentIndex, isTimeTraveling, stepBack, stepForward, resume } =\n * useTimeTravel(storeId, entries);\n *\n * return (\n * <div>\n * <button onClick={stepBack} disabled={currentIndex <= 0}>Back</button>\n * <button onClick={stepForward}>Forward</button>\n * {isTimeTraveling && <button onClick={resume}>Resume Live</button>}\n * <span>Index: {currentIndex} / {entries.length - 1}</span>\n * </div>\n * );\n * }\n * ```\n *\n * @param storeId - The store ID to time-travel, or `null` to disable.\n * @param entries - The event log entries (typically from {@link useEventLog}).\n * @returns An object with `currentIndex`, `isTimeTraveling`, `jumpTo`,\n * `stepBack`, `stepForward`, and `resume`.\n *\n * @public\n */\nexport function useTimeTravel(\n storeId: string | null,\n entries: EventLogEntry[],\n /**\n * Whether the selected store advertised the `replay` capability. Time-travel\n * commands are gated on it (DEV-4): the agent/core enforce it too, but the UI\n * should not send commands that will be dropped. Defaults to `true`.\n */\n canReplay: boolean = true,\n): {\n currentIndex: number;\n isTimeTraveling: boolean;\n /**\n * The store state reconstructed at the currently-viewed position (the\n * scrubbed index while traveling, otherwise the latest entry). `null` until\n * the baseline snapshot has been captured. Lets consumers render a live\n * preview of the state at any point in history.\n */\n previewState: unknown;\n /**\n * The event count the timeline is measured against: frozen at travel-start\n * so a live-emitting store cannot shift the scrubber, or `null` when live\n * (use `entries.length`). Consumers should size the slider/label off\n * `frameCount ?? entries.length`.\n */\n frameCount: number | null;\n jumpTo: (index: number) => void;\n stepBack: () => void;\n stepForward: () => void;\n resume: () => void;\n} {\n const { send, subscribe } = useHubConnection();\n const [currentIndex, setCurrentIndex] = useState(-1);\n const [isTimeTraveling, setIsTimeTraveling] = useState(false);\n\n // The event count frozen at the moment a travel session begins. While\n // traveling, the timeline (slider range, position label, forward boundary)\n // is measured against this frame instead of the live `entries.length`, so a\n // store that keeps emitting does not shift the scrubber under the user —\n // otherwise a fixed position appears to drift backward as the log grows.\n // `null` when live.\n const [frameCount, setFrameCount] = useState<number | null>(null);\n\n // The first STATE_SNAPSHOT received for this store, used as the baseline\n // for forward-replay state reconstruction. Only the first snapshot is\n // captured (the connect-time snapshot); time-travel response snapshots\n // sent back by the store are intentionally ignored so they don't overwrite\n // the baseline and corrupt future reconstructions.\n const baselineRef = useRef<{ state: unknown; version: number } | null>(null);\n\n useEffect(() => {\n // Reset baseline whenever the target store changes so a fresh snapshot\n // is captured for the new store.\n baselineRef.current = null;\n setFrameCount(null);\n if (!storeId) return;\n\n return subscribe((msg: DevtoolsMessage) => {\n if (\n msg.type === \"STATE_SNAPSHOT\" &&\n msg.storeId === storeId &&\n baselineRef.current === null\n ) {\n baselineRef.current = { state: msg.state, version: msg.version };\n }\n });\n }, [storeId, subscribe]);\n\n // Reconstruct the store state at a specific entries index by applying\n // each entry's patches sequentially from the baseline forward.\n // Returns null when no baseline has been captured yet (devtools still\n // waiting for the first STATE_SNAPSHOT).\n const buildStateAt = useCallback(\n (index: number): unknown => {\n const baseline = baselineRef.current;\n if (!baseline) return null;\n\n let state = baseline.state;\n for (let i = 0; i <= index; i++) {\n const entry = entries[i];\n if (!entry) break;\n // Skip entries that pre-date our baseline snapshot.\n if (entry.snapshotVersion <= baseline.version) continue;\n state = applyPatches(state as any, entry.patches);\n }\n return state;\n },\n [entries],\n );\n\n const jumpTo = useCallback(\n (index: number) => {\n // Do not send if the store can't replay (DEV-4) — the command would be a no-op.\n if (!storeId || !canReplay || index < 0 || index >= entries.length) return;\n\n // Freeze the timeline frame the first time we leave live, so subsequent\n // live events don't grow the slider range under the user.\n setFrameCount((prev) => prev ?? entries.length);\n setCurrentIndex(index);\n setIsTimeTraveling(true);\n\n const entry = entries[index]!;\n send({\n type: \"TIME_TRAVEL\",\n storeId,\n state: buildStateAt(index),\n snapshotVersion: entry.snapshotVersion,\n timestamp: new Date().toISOString(),\n sourceId: \"\",\n sourceRole: DevtoolsRole.EXTENSION,\n });\n },\n [storeId, entries, send, buildStateAt, canReplay],\n );\n\n const resume = useCallback(() => {\n setIsTimeTraveling(false);\n setCurrentIndex(-1);\n setFrameCount(null);\n // Restore the store to the latest known state by computing the state at\n // the last entry and sending a TIME_TRAVEL to snap it back (DEV-4: only if\n // the store can replay; the local reset above still runs regardless).\n if (canReplay && storeId && entries.length > 0) {\n const latestIndex = entries.length - 1;\n const latest = entries[latestIndex]!;\n send({\n type: \"TIME_TRAVEL\",\n storeId,\n state: buildStateAt(latestIndex),\n snapshotVersion: latest.snapshotVersion,\n timestamp: new Date().toISOString(),\n sourceId: \"\",\n sourceRole: DevtoolsRole.EXTENSION,\n });\n }\n }, [storeId, entries, send, buildStateAt, canReplay]);\n\n // While traveling the timeline is measured against the frozen frame, so\n // steps and boundaries ignore events that arrive mid-session.\n const timelineCount = frameCount ?? entries.length;\n\n const stepBack = useCallback(() => {\n const action = planStep(\"back\", {\n isTimeTraveling,\n currentIndex,\n entryCount: timelineCount,\n });\n if (action.kind === \"jump\") jumpTo(action.index);\n }, [isTimeTraveling, currentIndex, timelineCount, jumpTo]);\n\n const stepForward = useCallback(() => {\n const action = planStep(\"forward\", {\n isTimeTraveling,\n currentIndex,\n entryCount: timelineCount,\n });\n if (action.kind === \"jump\") jumpTo(action.index);\n else if (action.kind === \"resume\") resume();\n }, [isTimeTraveling, currentIndex, timelineCount, jumpTo, resume]);\n\n // The state at the currently-viewed position: the scrubbed index while\n // traveling, otherwise the newest entry. Recomputed from the baseline so the\n // preview follows both the slider and newly-arriving live events.\n const previewState = useMemo(\n () => buildStateAt(isTimeTraveling ? currentIndex : entries.length - 1),\n [buildStateAt, isTimeTraveling, currentIndex, entries.length],\n );\n\n return {\n currentIndex,\n isTimeTraveling,\n previewState,\n frameCount,\n jumpTo,\n stepBack,\n stepForward,\n resume,\n };\n}\n","/**\n * @module @yoltra/devtools-ui\n *\n * In-memory loopback transport: run the store agent, the hub, and the panel all\n * in one process (a browser tab or a test) with **no network socket**. This is\n * what powers the embeddable, zero-install DevTools demo — and it exercises the\n * exact same protocol the real WebSocket hub does, only over an in-page channel.\n */\n\nimport {\n DevtoolsRole,\n PROTOCOL_VERSION,\n type DevtoolsSocketCallbacks,\n type DevtoolsSocketFactory,\n type DevtoolsSocketHandle,\n} from \"@yoltra/devtools-protocol\";\n\n// Standard WebSocket readyState values.\nconst CONNECTING = 0;\nconst OPEN = 1;\nconst CLOSING = 2;\nconst CLOSED = 3;\n\n/** A party connected to the in-memory broker (agent or extension). */\ninterface Peer {\n role: DevtoolsRole | null; // resolved at handshake\n id: string | null;\n storeInfo?: { name: string; capabilities: unknown };\n deliver: (raw: string) => void; // push a message TO this peer's socket\n closed: boolean;\n}\n\n/** Hub-authored envelope fields (mirrors the real hub's `baseMsg`). */\nfunction hubMeta() {\n return {\n timestamp: new Date().toISOString(),\n sourceId: \"loopback-hub\",\n sourceRole: DevtoolsRole.HUB,\n };\n}\n\nfunction majorOf(version: string): string {\n return version.split(\".\")[0] ?? \"0\";\n}\n\n/**\n * A tiny in-process hub that speaks the DevTools protocol without any socket.\n * Stores fan their messages out to every extension; extension commands route to\n * the target store by `storeId`. Same routing contract as the real hub, minus\n * the WebSocket server (and its history buffer / origin checks, which are moot\n * in a single trusted process).\n */\nclass LoopbackBroker {\n private readonly peers = new Set<Peer>();\n\n add(deliver: (raw: string) => void): Peer {\n const peer: Peer = { role: null, id: null, deliver, closed: false };\n this.peers.add(peer);\n return peer;\n }\n\n remove(peer: Peer): void {\n if (!this.peers.delete(peer)) return;\n peer.closed = true;\n if (peer.role === DevtoolsRole.STORE && peer.id) {\n const msg = JSON.stringify({\n type: \"STORE_DISCONNECTED\",\n storeId: peer.id,\n reason: \"disconnected\",\n ...hubMeta(),\n });\n this.eachExtension((p) => p.deliver(msg));\n }\n }\n\n receive(peer: Peer, raw: string): void {\n if (peer.closed) return;\n let msg: Record<string, unknown> | null;\n try {\n msg = JSON.parse(raw);\n } catch {\n return;\n }\n if (msg === null || typeof msg !== \"object\" || typeof msg.type !== \"string\") return;\n\n if (peer.role === null) {\n this.handshake(peer, msg);\n return;\n }\n\n if (peer.role === DevtoolsRole.STORE) {\n // A store's messages fan out to every connected extension.\n this.eachExtension((p) => p.deliver(raw));\n } else if (typeof msg.storeId === \"string\") {\n // An extension's commands route to the target store.\n for (const p of this.peers) {\n if (p.role === DevtoolsRole.STORE && p.id === msg.storeId) p.deliver(raw);\n }\n }\n }\n\n private handshake(peer: Peer, msg: Record<string, any>): void {\n if (msg.type !== \"HANDSHAKE_REQUEST\") return;\n\n const role = msg.role as DevtoolsRole;\n const id =\n role === DevtoolsRole.STORE\n ? msg.store?.id\n : role === DevtoolsRole.EXTENSION\n ? msg.extension?.id\n : undefined;\n const compatible = majorOf(String(msg.protocolVersion ?? \"\")) === majorOf(PROTOCOL_VERSION);\n const success = compatible && typeof id === \"string\";\n\n peer.deliver(\n JSON.stringify({\n type: \"HANDSHAKE_RESPONSE\",\n success,\n protocolVersion: PROTOCOL_VERSION,\n ...hubMeta(),\n ...(success ? {} : { error: \"Loopback handshake rejected (version or id mismatch)\" }),\n }),\n );\n if (!success) return;\n\n peer.role = role;\n peer.id = id as string;\n\n if (role === DevtoolsRole.STORE) {\n peer.storeInfo = { name: msg.store?.name ?? id, capabilities: msg.store?.capabilities };\n const connected = JSON.stringify({\n type: \"STORE_CONNECTED\",\n store: { id, name: peer.storeInfo.name, capabilities: peer.storeInfo.capabilities },\n ...hubMeta(),\n });\n this.eachExtension((p) => p.deliver(connected));\n } else {\n const stores = [...this.peers]\n .filter((p) => p.role === DevtoolsRole.STORE && p.storeInfo)\n .map((p) => ({\n id: p.id,\n name: p.storeInfo!.name,\n status: \"connected\" as const,\n capabilities: p.storeInfo!.capabilities,\n connectedAt: new Date().toISOString(),\n }));\n peer.deliver(JSON.stringify({ type: \"STORE_REGISTRY\", stores, ...hubMeta() }));\n }\n }\n\n private eachExtension(fn: (p: Peer) => void): void {\n for (const p of this.peers) if (p.role === DevtoolsRole.EXTENSION) fn(p);\n }\n}\n\n/**\n * A loopback hub instance. Wire the agent and the panel to the *same* instance.\n *\n * @public\n */\nexport interface LoopbackHub {\n /** Inject into the browser agent: `withDevtools(store, { socketFactory })`. */\n agentSocketFactory: DevtoolsSocketFactory;\n /** Pass to the DevTools UI as `config.WebSocket` (e.g. `<DevtoolsApp>`). */\n WebSocket: { new (url: string): WebSocket };\n}\n\n/**\n * Creates a self-contained in-memory DevTools hub plus the two client transports\n * that connect to it — a `socketFactory` for the store agent and a\n * `WebSocket`-compatible class for the panel UI. No ports, no server, no\n * extension: everything runs in the current process.\n *\n * @example\n * ```ts\n * const hub = createLoopbackHub();\n * withDevtools(store, { port: 0, socketFactory: hub.agentSocketFactory });\n * // <DevtoolsApp config={{ port: 0, WebSocket: hub.WebSocket }} />\n * ```\n *\n * @public\n */\nexport function createLoopbackHub(): LoopbackHub {\n const broker = new LoopbackBroker();\n\n const agentSocketFactory: DevtoolsSocketFactory = (\n _url: string,\n callbacks: DevtoolsSocketCallbacks,\n ): DevtoolsSocketHandle => {\n let readyState = CONNECTING;\n const peer = broker.add((raw) => callbacks.onMessage(raw));\n queueMicrotask(() => {\n readyState = OPEN;\n callbacks.onOpen();\n });\n return {\n get readyState() {\n return readyState;\n },\n send: (data) => broker.receive(peer, data),\n close: () => {\n if (readyState === CLOSED) return;\n readyState = CLOSED;\n broker.remove(peer);\n callbacks.onClose();\n },\n dispose: () => {\n peer.closed = true;\n },\n };\n };\n\n class LoopbackWebSocket {\n static readonly CONNECTING = CONNECTING;\n static readonly OPEN = OPEN;\n static readonly CLOSING = CLOSING;\n static readonly CLOSED = CLOSED;\n\n onopen: (() => void) | null = null;\n onmessage: ((ev: { data: string }) => void) | null = null;\n onclose: (() => void) | null = null;\n onerror: (() => void) | null = null;\n readyState = CONNECTING;\n\n private readonly peer: Peer;\n\n constructor(_url: string) {\n this.peer = broker.add((raw) => this.onmessage?.({ data: raw }));\n queueMicrotask(() => {\n this.readyState = OPEN;\n this.onopen?.();\n });\n }\n\n send(data: string): void {\n broker.receive(this.peer, data);\n }\n\n close(): void {\n if (this.readyState === CLOSED) return;\n this.readyState = CLOSED;\n broker.remove(this.peer);\n this.onclose?.();\n }\n }\n\n return {\n agentSocketFactory,\n WebSocket: LoopbackWebSocket as unknown as { new (url: string): WebSocket },\n };\n}\n"],"names":["noop","HubContext","createContext","REACT_ELEMENT_TYPE","REACT_FRAGMENT_TYPE","jsxProd","type","config","maybeKey","key","propName","reactJsxRuntime_production","getComponentNameFromType","REACT_CLIENT_REFERENCE","REACT_PROFILER_TYPE","REACT_STRICT_MODE_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_ACTIVITY_TYPE","REACT_PORTAL_TYPE","REACT_CONTEXT_TYPE","REACT_CONSUMER_TYPE","REACT_FORWARD_REF_TYPE","innerType","REACT_MEMO_TYPE","REACT_LAZY_TYPE","testStringCoercion","value","checkKeyStringCoercion","JSCompiler_inline_result","JSCompiler_temp_const","JSCompiler_inline_result$jscomp$0","getTaskName","name","getOwner","dispatcher","ReactSharedInternals","UnknownOwner","hasValidKey","hasOwnProperty","getter","defineKeyPropWarningGetter","props","displayName","warnAboutAccessingKey","specialPropKeyWarningShown","elementRefGetterWithDeprecationWarning","componentName","didWarnAboutElementRef","ReactElement","self","source","owner","debugStack","debugTask","jsxDEVImpl","isStaticChildren","children","isArrayImpl","validateChildKeys","keys","k","didWarnAboutKeySpread","node","React","require$$0","createTask","callStackForError","unknownOwnerDebugStack","unknownOwnerDebugTask","reactJsxRuntime_development","trackActualOwner","jsxRuntimeModule","require$$1","DEFAULT_CAPABILITIES","RECONNECT_BASE_MS","RECONNECT_MAX_MS","HubProvider","status","setStatus","useState","wsRef","useRef","subscribersRef","reconnectAttemptRef","reconnectTimerRef","extensionIdRef","configRef","connect","useCallback","cfg","url","WS","ws","handshake","PROTOCOL_VERSION","DevtoolsRole","event","raw","msg","handler","autoReconnect","maxAttempts","attempt","delay","disconnect","reconnect","send","message","subscribe","useEffect","jsx","useHubConnection","useContext","useEventEmitter","storeId","channel","payload","DEFAULT_MAX_ENTRIES","useEventLog","options","maxEntries","allEntriesRef","maxRef","setTick","sid","entry","next","t","clear","useEventReplay","snapshot","events","e","useStoreMetrics","metrics","setMetrics","loading","setLoading","intervalMs","timerRef","requestMetrics","unsub","useStoreRegistry","stores","setStores","prev","s","applyPatches","target","patches","result","patch","segments","parsePointer","setAtPath","removeAtPath","pointer","FORBIDDEN_KEYS","obj","insert","head","rest","index","startSnapshotRetry","scheduler","h","ms","id","cancel","SNAPSHOT_RETRY_INTERVAL_MS","useStoreState","state","setState","version","setVersion","versionRef","pendingPatchesRef","cancelRetryRef","stopRetry","requestState","pending","p","a","b","current","lastVersion","useStoreSubscriptions","data","setData","requestSubscriptions","planStep","direction","isTimeTraveling","currentIndex","entryCount","lastIndex","useTimeTravel","entries","canReplay","setCurrentIndex","setIsTimeTraveling","frameCount","setFrameCount","baselineRef","buildStateAt","baseline","i","jumpTo","resume","latestIndex","latest","timelineCount","stepBack","action","stepForward","previewState","useMemo","CONNECTING","OPEN","CLOSING","CLOSED","hubMeta","majorOf","LoopbackBroker","deliver","peer","role","success","connected","fn","createLoopbackHub","broker","agentSocketFactory","_url","callbacks","readyState","_LoopbackWebSocket","LoopbackWebSocket"],"mappings":"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","x_google_ignoreList":[1,2,3]}