@xstate-devtools/adapter 0.1.3 → 0.1.4
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 +49 -0
- package/dist/chunk-3GM2SFT4.js +680 -0
- package/dist/chunk-3GM2SFT4.js.map +1 -0
- package/dist/chunk-MHHRMHW5.js +62 -0
- package/dist/chunk-MHHRMHW5.js.map +1 -0
- package/dist/index.cjs +753 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +790 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +12 -0
- package/dist/react.d.ts +12 -0
- package/dist/react.js +43 -0
- package/dist/react.js.map +1 -0
- package/dist/server.cjs +936 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +29 -0
- package/dist/server.d.ts +29 -0
- package/dist/server.js +235 -0
- package/dist/server.js.map +1 -0
- package/package.json +46 -6
- package/src/core.test.ts +0 -287
- package/src/core.ts +0 -667
- package/src/index.ts +0 -73
- package/src/logging.test.ts +0 -39
- package/src/logging.ts +0 -40
- package/src/react.tsx +0 -50
- package/src/sanitize.test.ts +0 -68
- package/src/sanitize.ts +0 -70
- package/src/serialize.test.ts +0 -170
- package/src/serialize.ts +0 -148
- package/src/server.ts +0 -310
- package/tsconfig.json +0 -14
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/logging.ts","../src/sanitize.ts","../src/serialize.ts","../src/core.ts"],"sourcesContent":["// Server entrypoint — exposes a WebSocket bridge so the DevTools panel\n// can connect to actors running in Node.\nimport { createServer as createTcpServer } from 'node:net'\nimport type {\n ExtensionToPageMessage,\n PageToExtensionMessage,\n} from '../../extension/src/shared/types.js'\nimport { createInspector, type Transport } from './core.js'\nimport {\n debugLog as baseDebugLog,\n infoLog as baseInfoLog,\n warnLog as baseWarnLog,\n} from './logging.js'\nimport { sanitize } from './sanitize.js'\n\n/**\n * Find the lowest TCP port >= `start` that is not currently in use.\n * Uses a temporary TCP server to probe; the port is released before resolving.\n */\nfunction getAvailablePort(start: number): Promise<number> {\n return new Promise((resolve, reject) => {\n const probe = createTcpServer()\n probe.unref()\n probe.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n resolve(getAvailablePort(start + 1))\n } else {\n reject(err)\n }\n })\n probe.listen(start, '127.0.0.1', () => {\n const port = (probe.address() as { port: number }).port\n probe.close(() => resolve(port))\n })\n })\n}\n\nexport interface ServerAdapterOptions {\n /** Port to listen on. Defaults to env XSTATE_DEVTOOLS_PORT or 9301. */\n port?: number\n /** Host to bind. Defaults to '127.0.0.1'. */\n host?: string\n /** Max messages to buffer while no panel is connected. Default 200. */\n bufferSize?: number\n}\n\ninterface ClientLike {\n send(data: string): void\n on(event: string, listener: (...args: unknown[]) => void): void\n readyState: number\n}\n\nconst OPEN_STATE = 1\n\nfunction summarizeMessage(message: ExtensionToPageMessage | PageToExtensionMessage) {\n const summary: Record<string, unknown> = { type: message.type }\n if ('sessionId' in message) summary.sessionId = message.sessionId\n if ('parentSessionId' in message && message.parentSessionId) {\n summary.parentSessionId = message.parentSessionId\n }\n if ('globalSeq' in message) summary.globalSeq = message.globalSeq\n if ('timestamp' in message) summary.timestamp = message.timestamp\n if (\n 'event' in message &&\n message.event &&\n typeof message.event === 'object' &&\n 'type' in message.event\n ) {\n summary.eventType = message.event.type\n }\n return summary\n}\n\nfunction debugLog(message: string, details?: unknown) {\n baseDebugLog('server', message, details)\n}\n\nfunction infoLog(message: string, details?: unknown) {\n baseInfoLog('server', message, details)\n}\n\nfunction warnLog(message: string, details?: unknown) {\n baseWarnLog('server', message, details)\n}\n\nfunction stringifyOutgoingMessage(message: PageToExtensionMessage): string | null {\n const payload = { ...message, __xstateDevtools: true as const }\n\n try {\n return JSON.stringify(payload)\n } catch (error) {\n warnLog('failed to stringify adapter message; retrying with sanitized payload', {\n error,\n message: summarizeMessage(message),\n })\n }\n\n try {\n return JSON.stringify(sanitize(payload))\n } catch (error) {\n warnLog('dropping adapter message that could not be stringified', {\n error,\n message: summarizeMessage(message),\n })\n return null\n }\n}\n\ninterface CachedServer {\n clients: Set<ClientLike>\n dispatchHandlers: Set<(msg: ExtensionToPageMessage) => void>\n buffer: string[]\n bufferSize: number\n activated: boolean\n /** Resolves with the actual TCP port once the WS server is listening. */\n port: Promise<number>\n close: () => void\n}\n\n/**\n * Start a local WebSocket server that the DevTools panel can connect to.\n * Returns the inspector callback. Multiple panels can connect simultaneously.\n *\n * The WS server, connected clients, dispatch handlers, and pre-connection\n * buffer are all stashed on globalThis keyed by port. This makes the function\n * idempotent across HMR re-evaluation: subsequent calls reuse the existing\n * server and only register new inspector hooks.\n *\n * Inspection events emitted before the first panel connects are buffered (up\n * to `bufferSize`, default 200) and flushed to the first connecting client so\n * actors registered at boot are visible.\n */\nexport function createServerAdapter(options: ServerAdapterOptions = {}) {\n const port = options.port ?? (Number(process.env.XSTATE_DEVTOOLS_PORT) || 9301)\n const host = options.host ?? '127.0.0.1'\n const bufferSize = options.bufferSize ?? 200\n infoLog('createServerAdapter called', { host, port, bufferSize })\n\n const key = `__xstate_devtools_server_${port}__`\n const cache = (globalThis as Record<string, unknown>)[key] as CachedServer | undefined\n\n let server: CachedServer\n if (cache) {\n server = cache\n infoLog('reusing cached WebSocket server', {\n host,\n port,\n clientCount: server.clients.size,\n bufferedMessages: server.buffer.length,\n })\n // honour the most recent caller's buffer size if larger\n if (bufferSize > server.bufferSize) server.bufferSize = bufferSize\n } else {\n const clients = new Set<ClientLike>()\n const dispatchHandlers = new Set<(msg: ExtensionToPageMessage) => void>()\n const buffer: string[] = []\n let wss: any = null\n let closed = false\n\n let portResolve!: (port: number) => void\n let portReject!: (err: unknown) => void\n const portPromise = new Promise<number>((res, rej) => {\n portResolve = res\n portReject = rej\n })\n\n server = {\n clients,\n dispatchHandlers,\n buffer,\n bufferSize,\n activated: false,\n port: portPromise,\n close: () => {\n closed = true\n infoLog('closing WebSocket server', { host, port, clientCount: clients.size })\n try {\n wss?.close()\n } catch {\n /* noop */\n }\n clients.clear()\n dispatchHandlers.clear()\n buffer.length = 0\n delete (globalThis as Record<string, unknown>)[key]\n },\n }\n\n // Lazily import ws so this module is import-safe in environments that\n // never use the server entrypoint (or where ws isn't installed).\n void (async () => {\n try {\n const mod = await import('ws')\n const WSServer = (mod as any).WebSocketServer ?? (mod as any).Server\n if (closed) return\n const actualPort = await getAvailablePort(port)\n if (closed) return\n wss = new WSServer({ port: actualPort, host })\n process.env.XSTATE_DEVTOOLS_PORT = String(actualPort)\n portResolve(actualPort)\n infoLog('WebSocket server listening', { host, port: actualPort })\n wss.on('connection', (ws: ClientLike) => {\n infoLog('panel connected to WebSocket server', {\n host,\n port,\n activated: server.activated,\n bufferedMessages: server.buffer.length,\n })\n // Drain bootstrap buffer to the first client only.\n if (!server.activated) {\n server.activated = true\n infoLog('flushing bootstrap buffer to first panel', {\n host,\n port,\n bufferedMessages: server.buffer.length,\n })\n for (const payload of server.buffer) {\n try {\n ws.send(payload)\n } catch {\n /* ignore */\n }\n }\n server.buffer.length = 0\n }\n server.clients.add(ws)\n ws.on('message', (raw: unknown) => {\n try {\n const text = typeof raw === 'string' ? raw : (raw as Buffer).toString('utf8')\n const msg = JSON.parse(text) as ExtensionToPageMessage\n debugLog('received dispatch from panel', summarizeMessage(msg))\n for (const cb of server.dispatchHandlers) cb(msg)\n } catch (error) {\n warnLog('failed to parse panel message', { error })\n }\n })\n ws.on('close', () => {\n server.clients.delete(ws)\n infoLog('panel disconnected from WebSocket server', {\n host,\n port,\n clientCount: server.clients.size,\n })\n })\n ws.on('error', (error: unknown) => {\n server.clients.delete(ws)\n warnLog('WebSocket client error', { error })\n })\n })\n wss.on('error', (err: Error) => {\n warnLog('WS server error', { host, port, message: err.message })\n })\n } catch (e) {\n portReject(e)\n warnLog('could not start server adapter — install `ws` to enable', {\n host,\n port,\n message: (e as Error).message,\n })\n }\n })()\n\n ;(globalThis as Record<string, unknown>)[key] = server\n }\n\n const transport: Transport = {\n send(message: PageToExtensionMessage) {\n const payload = stringifyOutgoingMessage(message)\n if (payload === null) return\n\n if (!server.activated) {\n // No panel has connected yet — buffer for the first one.\n if (server.buffer.length >= server.bufferSize) server.buffer.shift()\n server.buffer.push(payload)\n debugLog('buffered outgoing adapter message; no panel connected yet', {\n bufferedMessages: server.buffer.length,\n message: summarizeMessage(message),\n })\n return\n }\n let sentCount = 0\n for (const ws of server.clients) {\n if (ws.readyState === OPEN_STATE) {\n try {\n ws.send(payload)\n sentCount += 1\n } catch {\n /* ignore */\n }\n }\n }\n debugLog('sent adapter message to connected panels', {\n sentCount,\n clientCount: server.clients.size,\n message: summarizeMessage(message),\n })\n },\n subscribe(handler) {\n server.dispatchHandlers.add(handler)\n debugLog('registered dispatch handler', { handlerCount: server.dispatchHandlers.size })\n return () => {\n server.dispatchHandlers.delete(handler)\n debugLog('removed dispatch handler', { handlerCount: server.dispatchHandlers.size })\n }\n },\n }\n\n const inspector = createInspector(transport, 'srv')\n return { ...inspector, close: server.close, port: server.port }\n}\n","type LogLevel = 'debug' | 'info' | 'warn'\n\ndeclare global {\n var __XSTATE_DEVTOOLS_LOGGING__: boolean | undefined\n}\n\nfunction hasProcessEnv() {\n return typeof process !== 'undefined' && typeof process.env !== 'undefined'\n}\n\nexport function isLoggingEnabled() {\n if (globalThis.__XSTATE_DEVTOOLS_LOGGING__ === true) return true\n if (!hasProcessEnv()) return false\n\n const value = process.env.XSTATE_DEVTOOLS_LOGGING\n return value === '1' || value === 'true'\n}\n\nfunction log(level: LogLevel, scope: string, message: string, details?: unknown) {\n if (!isLoggingEnabled()) return\n\n if (details === undefined) {\n console[level](`[xstate-devtools:${scope}] ${message}`)\n return\n }\n\n console[level](`[xstate-devtools:${scope}] ${message}`, details)\n}\n\nexport function debugLog(scope: string, message: string, details?: unknown) {\n log('debug', scope, message, details)\n}\n\nexport function infoLog(scope: string, message: string, details?: unknown) {\n log('info', scope, message, details)\n}\n\nexport function warnLog(scope: string, message: string, details?: unknown) {\n log('warn', scope, message, details)\n}\n","// packages/adapter/src/sanitize.ts\n\nconst MAX_DEPTH = 10\nconst MAX_STRING_LENGTH = 500\nconst MAX_ARRAY_LENGTH = 100\n\nfunction sanitizeValue(value: unknown, depth: number, seen: WeakSet<object>): unknown {\n if (depth > MAX_DEPTH) return '[MaxDepth]'\n if (value === null || value === undefined) return value\n if (typeof value === 'boolean' || typeof value === 'number') return value\n if (typeof value === 'string') {\n return value.length > MAX_STRING_LENGTH ? `${value.slice(0, MAX_STRING_LENGTH)}…` : value\n }\n if (typeof value === 'function') return `[Function: ${value.name || '(anonymous)'}]`\n if (typeof value === 'symbol') return `[Symbol: ${value.description ?? ''}]`\n if (typeof value === 'bigint') return `[BigInt: ${value}]`\n if (value instanceof Error) return { __type: 'Error', name: value.name, message: value.message }\n if (value instanceof Date) return { __type: 'Date', iso: value.toISOString() }\n if (value instanceof RegExp) return { __type: 'RegExp', source: value.source, flags: value.flags }\n if (typeof value === 'object') {\n if (seen.has(value)) return '[Circular]'\n seen.add(value)\n }\n if (value instanceof Map) {\n const entries: [unknown, unknown][] = []\n for (const [k, v] of value as Map<unknown, unknown>) {\n if (entries.length >= MAX_ARRAY_LENGTH) break\n entries.push([sanitizeValue(k, depth + 1, seen), sanitizeValue(v, depth + 1, seen)])\n }\n return { __type: 'Map', entries }\n }\n if (value instanceof Set) {\n const values: unknown[] = []\n for (const v of value as Set<unknown>) {\n if (values.length >= MAX_ARRAY_LENGTH) break\n values.push(sanitizeValue(v, depth + 1, seen))\n }\n return { __type: 'Set', values }\n }\n if (value instanceof Promise) return '[Promise]'\n if (value instanceof WeakMap || value instanceof WeakSet) return '[WeakCollection]'\n if (ArrayBuffer.isView(value)) return `[TypedArray: ${(value as any).constructor.name}]`\n // Detect DOM nodes (works in browser and is safe to check)\n if (typeof Node !== 'undefined' && value instanceof Node) {\n return `[DOMNode: ${(value as Element).tagName ?? value.nodeName}]`\n }\n if (Array.isArray(value)) {\n const sliced = value.slice(0, MAX_ARRAY_LENGTH)\n const result = sliced.map((v) => sanitizeValue(v, depth + 1, seen))\n if (value.length > MAX_ARRAY_LENGTH) result.push(`[…${value.length - MAX_ARRAY_LENGTH} more]`)\n return result\n }\n if (typeof value === 'object') {\n const result: Record<string, unknown> = {}\n let count = 0\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (count++ >= MAX_ARRAY_LENGTH) {\n result['…'] = '[truncated]'\n break\n }\n result[k] = sanitizeValue(v, depth + 1, seen)\n }\n return result\n }\n return String(value)\n}\n\nexport function sanitize(value: unknown, depth = 0): unknown {\n return sanitizeValue(value, depth, new WeakSet<object>())\n}\n","// packages/adapter/src/serialize.ts\nimport type { AnyStateMachine } from 'xstate'\nimport type {\n SerializedInvoke,\n SerializedMachine,\n SerializedStateNode,\n SerializedTransition,\n} from '../../extension/src/shared/types.js'\n\nconst MAX_SERIALIZED_NODES = 500\nconst MAX_TRANSITIONS_PER_NODE = 100\nconst MAX_CHILD_STATES = 100\nconst MAX_ACTIONS_PER_TRANSITION = 20\nconst MAX_ENTRY_EXIT_ACTIONS = 20\nconst MAX_INVOKES_PER_NODE = 20\n\nfunction serializeGuard(guard: unknown): string | undefined {\n if (!guard) return undefined\n if (typeof guard === 'string') return guard\n if (typeof guard === 'function') return (guard as Function).name || '(inline)'\n if (typeof guard === 'object' && guard !== null) {\n const g = guard as any\n return g.type ?? g.name ?? '(inline)'\n }\n return '(inline)'\n}\n\nfunction serializeAction(action: unknown): string {\n if (typeof action === 'string') return action\n if (typeof action === 'function') return (action as Function).name || '(anonymous)'\n if (typeof action === 'object' && action !== null) {\n const a = action as any\n return a.type ?? a.name ?? String(action)\n }\n return String(action)\n}\n\nfunction serializeTransitionList(transitions: any[]): SerializedTransition[] {\n return transitions.slice(0, MAX_TRANSITIONS_PER_NODE).map((t: any) => ({\n eventType: t.eventType ?? '',\n targets: (t.target ?? []).map((n: any) => n?.id ?? String(n)).filter(Boolean),\n guard: serializeGuard(t.guard),\n actions: (t.actions ?? [])\n .slice(0, MAX_ACTIONS_PER_TRANSITION)\n .map(serializeAction)\n .filter(Boolean),\n }))\n}\n\nfunction serializeInvokes(node: any): SerializedInvoke[] {\n return (node.invoke as any[]).slice(0, MAX_INVOKES_PER_NODE).map((inv: any) => ({\n id: inv.id ?? '(unknown)',\n src: typeof inv.src === 'string' ? inv.src : (inv.src?.id ?? inv.src?.name ?? '(inline)'),\n }))\n}\n\ninterface SerializeState {\n seen: WeakSet<object>\n count: number\n}\n\nfunction serializeNode(node: any, state: SerializeState): SerializedStateNode {\n if (!node || typeof node !== 'object') {\n return {\n id: '(unknown)',\n key: '(unknown)',\n type: 'atomic',\n states: {},\n on: [],\n always: [],\n entry: [],\n exit: [],\n invoke: [],\n }\n }\n\n if (state.count >= MAX_SERIALIZED_NODES) {\n return {\n id: node.id ?? '(truncated)',\n key: node.key ?? '(truncated)',\n type: node.type ?? 'atomic',\n states: {},\n on: [],\n always: [],\n entry: [],\n exit: [],\n invoke: [],\n }\n }\n\n if (state.seen.has(node)) {\n return {\n id: node.id ?? '(circular)',\n key: node.key ?? '(circular)',\n type: node.type ?? 'atomic',\n states: {},\n on: [],\n always: [],\n entry: [],\n exit: [],\n invoke: [],\n }\n }\n\n state.seen.add(node)\n state.count += 1\n\n const allTransitions: SerializedTransition[] = []\n if (node.transitions instanceof Map) {\n for (const [, tList] of node.transitions) {\n if (allTransitions.length >= MAX_TRANSITIONS_PER_NODE) break\n allTransitions.push(...serializeTransitionList(tList))\n if (allTransitions.length >= MAX_TRANSITIONS_PER_NODE) {\n allTransitions.length = MAX_TRANSITIONS_PER_NODE\n break\n }\n }\n }\n\n const always = Array.isArray(node.always) ? serializeTransitionList(node.always) : []\n const childEntries = Object.entries(node.states ?? {}).slice(0, MAX_CHILD_STATES)\n\n return {\n id: node.id,\n key: node.key,\n type: node.type,\n initial: node.initial?.target?.[0]?.key,\n states: Object.fromEntries(childEntries.map(([k, v]) => [k, serializeNode(v, state)])),\n on: allTransitions,\n always,\n entry: (node.entry ?? []).slice(0, MAX_ENTRY_EXIT_ACTIONS).map(serializeAction).filter(Boolean),\n exit: (node.exit ?? []).slice(0, MAX_ENTRY_EXIT_ACTIONS).map(serializeAction).filter(Boolean),\n invoke: serializeInvokes(node),\n sourceLocation: node.config?.__xstateDevtoolsSource ?? undefined,\n description: node.config?.description ?? undefined,\n }\n}\n\nexport function serializeMachine(\n machine: AnyStateMachine,\n sourceLocation?: string,\n): SerializedMachine {\n return {\n id: machine.id,\n root: serializeNode(machine.root, { seen: new WeakSet<object>(), count: 0 }),\n sourceLocation,\n }\n}\n","// Transport-agnostic XState inspection core.\n// Browser and server entrypoints supply their own transports.\nimport type { AnyActorRef } from 'xstate'\nimport type {\n ExtensionToPageMessage,\n PageToExtensionMessage,\n SerializedEvent,\n SerializedMachine,\n SerializedSnapshot,\n} from '../../extension/src/shared/types.js'\nimport {\n debugLog as baseDebugLog,\n infoLog as baseInfoLog,\n warnLog as baseWarnLog,\n} from './logging.js'\nimport { sanitize } from './sanitize.js'\nimport { serializeMachine } from './serialize.js'\n\nexport type Source = 'web' | 'srv'\n\nexport interface InspectorOptions {\n /**\n * Absolute filesystem root for the web app. When provided, web stack frames\n * like http://localhost:5173/app/... are remapped to <webSourceRoot>/app/...\n * so VS Code source links can open local files.\n */\n webSourceRoot?: string\n}\n\nexport interface Transport {\n /** Send a protocol message outbound (toward the panel). */\n send: (message: PageToExtensionMessage) => void\n /** Subscribe to inbound dispatch messages from the panel. Returns a teardown. */\n subscribe: (handler: (message: ExtensionToPageMessage) => void) => () => void\n}\n\ntype StateValue = string | { [key: string]: StateValue }\n\ninterface StateNodeLike {\n id: string\n key: string\n type: 'atomic' | 'compound' | 'parallel' | 'final' | 'history' | string\n parent?: StateNodeLike\n states?: Record<string, StateNodeLike>\n initial?: string | { target?: StateNodeLike[] }\n}\n\ninterface MachineLike {\n root: StateNodeLike\n getStateNodeById: (id: string) => StateNodeLike\n resolveState: (snapshot: {\n value: unknown\n context?: unknown\n status?: string\n output?: unknown\n error?: unknown\n historyValue?: unknown\n }) => unknown\n}\n\ninterface MutableActorRef extends AnyActorRef {\n logic?: MachineLike\n update?: (snapshot: unknown, event: { type: string; stateNodeId: string }) => void\n}\n\nfunction summarizeMessage(message: ExtensionToPageMessage | PageToExtensionMessage) {\n const summary: Record<string, unknown> = { type: message.type }\n if ('sessionId' in message) summary.sessionId = message.sessionId\n if ('stateNodeId' in message) summary.stateNodeId = message.stateNodeId\n if ('parentSessionId' in message && message.parentSessionId) {\n summary.parentSessionId = message.parentSessionId\n }\n if ('globalSeq' in message) summary.globalSeq = message.globalSeq\n if ('timestamp' in message) summary.timestamp = message.timestamp\n if (\n 'event' in message &&\n message.event &&\n typeof message.event === 'object' &&\n 'type' in message.event\n ) {\n summary.eventType = message.event.type\n }\n return summary\n}\n\nfunction summarizeInspectionEvent(event: any) {\n return {\n type: event?.type,\n sessionId: event?.actorRef?.sessionId,\n eventType:\n event?.type === '@xstate.event' && event?.event && typeof event.event === 'object'\n ? event.event.type\n : undefined,\n }\n}\n\nfunction debugLog(source: Source, message: string, details?: unknown) {\n baseDebugLog(`${source}:adapter`, message, details)\n}\n\nfunction infoLog(source: Source, message: string, details?: unknown) {\n baseInfoLog(`${source}:adapter`, message, details)\n}\n\nfunction warnLog(source: Source, message: string, details?: unknown) {\n baseWarnLog(`${source}:adapter`, message, details)\n}\n\nfunction isLibraryStackFrame(line: string): boolean {\n const normalized = line.replace(/\\\\/g, '/').toLowerCase()\n return (\n normalized.includes('/node_modules/xstate/') ||\n normalized.includes('/node_modules/@xstate/') ||\n normalized.includes('/@xstate-devtools/adapter/') ||\n normalized.includes('/packages/adapter/')\n )\n}\n\nfunction normalizeStackFrame(line: string): string {\n return line.trim().replace(/^at\\s+/, '')\n}\n\nfunction extractStackFrameLocation(frame: string): string {\n return frame.match(/\\((.*)\\)$/)?.[1] ?? frame\n}\n\nfunction isAnonymousOrEvalLocation(location: string): boolean {\n const normalized = location\n .trim()\n .toLowerCase()\n .replace(/^[./\\\\]+/, '')\n\n return (\n normalized === '<anonymous>' ||\n normalized === 'anonymous' ||\n normalized === '(anonymous)' ||\n normalized === 'eval' ||\n normalized === '<eval>' ||\n normalized === '[native code]'\n )\n}\n\nfunction hasFilesystemBackedPath(location: string): boolean {\n const trimmed = location.trim()\n if (!trimmed) return false\n\n const match = trimmed.match(/^(.*?)(?::\\d+)?(?::\\d+)?$/)\n const rawPath = (match?.[1] ?? trimmed).trim()\n if (!rawPath || isAnonymousOrEvalLocation(rawPath)) return false\n\n if (/^[a-zA-Z]:[\\\\/]/.test(rawPath)) return true\n if (rawPath.startsWith('/') || rawPath.startsWith('./') || rawPath.startsWith('../')) return true\n\n if (/^[a-zA-Z][a-zA-Z\\d+.-]*:\\/\\//.test(rawPath)) {\n try {\n const url = new URL(rawPath)\n if (url.protocol === 'file:') return true\n return url.pathname.startsWith('/@fs/')\n } catch {\n return false\n }\n }\n\n return false\n}\n\nfunction remapWebUrlLocationToFsPath(\n location: string,\n source: Source,\n options?: InspectorOptions,\n): string {\n if (source !== 'web' || !options?.webSourceRoot) return location\n\n const match = location.trim().match(/^(.*?)(?::(\\d+))?(?::(\\d+))?$/)\n if (!match) return location\n\n const [, rawPath, line, column] = match\n if (!rawPath || !/^https?:\\/\\//.test(rawPath)) return location\n\n try {\n const url = new URL(rawPath)\n const pathname = decodeURIComponent(url.pathname)\n if (!pathname.startsWith('/app/')) return location\n\n const root = options.webSourceRoot.replace(/\\/+$/, '')\n const filePath = `${root}${pathname}`\n const suffix = line ? `:${line}${column ? `:${column}` : ''}` : ''\n return `${filePath}${suffix}`\n } catch {\n return location\n }\n}\n\nexport function getSourceLocationFromStack(\n stack?: string,\n source: Source = 'web',\n options?: InspectorOptions,\n): string | undefined {\n const lines = stack?.split('\\n') ?? []\n\n for (let i = 0; i < lines.length; i += 1) {\n if (i <= 2) continue\n\n const line = lines[i]\n if (isLibraryStackFrame(line)) continue\n\n const normalizedFrame = normalizeStackFrame(line)\n const location = remapWebUrlLocationToFsPath(\n extractStackFrameLocation(normalizedFrame),\n source,\n options,\n )\n\n if (!hasFilesystemBackedPath(location)) continue\n\n const wrapped = normalizedFrame.match(/\\((.*)\\)$/)\n if (wrapped) {\n return normalizedFrame.replace(wrapped[1], location)\n }\n\n return location\n }\n\n return undefined\n}\n\nfunction getSourceLocation(source: Source, options?: InspectorOptions): string | undefined {\n try {\n const oldLimit = Error.stackTraceLimit\n Error.stackTraceLimit = 50\n const stack = new Error().stack\n Error.stackTraceLimit = oldLimit\n return getSourceLocationFromStack(stack, source, options)\n } catch {\n return undefined\n }\n}\n\nfunction serializeSnapshot(snapshot: any): SerializedSnapshot {\n return {\n value: snapshot?.value ?? null,\n context: sanitize(snapshot?.context),\n status: snapshot?.status ?? 'active',\n error: snapshot?.error ? sanitize(snapshot.error) : undefined,\n }\n}\n\nfunction safeSerializeSnapshot(actorRef: AnyActorRef): SerializedSnapshot {\n try {\n return serializeSnapshot(actorRef.getSnapshot())\n } catch {\n return { value: null, context: undefined, status: 'active' }\n }\n}\n\nfunction getActorDisplayName(actorRef: AnyActorRef): string | undefined {\n const actor = actorRef as {\n logic?: { id?: string; src?: unknown; name?: string } | undefined\n src?: unknown\n }\n\n const src = actor.src ?? actor.logic?.src\n if (typeof src === 'string' && src.length > 0) return src\n if (typeof actor.logic?.id === 'string' && actor.logic.id.length > 0) return actor.logic.id\n if (typeof actor.logic?.name === 'string' && actor.logic.name.length > 0) return actor.logic.name\n if (src && typeof src === 'object') {\n const namedSrc = src as { id?: string; name?: string }\n if (typeof namedSrc.id === 'string' && namedSrc.id.length > 0) return namedSrc.id\n if (typeof namedSrc.name === 'string' && namedSrc.name.length > 0) return namedSrc.name\n }\n return undefined\n}\n\nfunction getNodeInitialChild(node: StateNodeLike): StateNodeLike | null {\n if (!node.states) return null\n if (typeof node.initial === 'string') {\n return node.states[node.initial] ?? null\n }\n\n const target = Array.isArray(node.initial?.target) ? node.initial.target[0] : null\n return target ?? null\n}\n\nfunction encodeChildValue(child: StateNodeLike, childValue: StateValue): StateValue {\n if (child.type === 'atomic' || child.type === 'final' || child.type === 'history') {\n return child.key\n }\n\n return { [child.key]: childValue }\n}\n\nfunction getDefaultStateValue(node: StateNodeLike): StateValue {\n if (node.type === 'parallel') {\n const value: Record<string, StateValue> = {}\n for (const child of Object.values(node.states ?? {})) {\n value[child.key] = getDefaultSelectionValue(child)\n }\n return value\n }\n\n const initialChild = getNodeInitialChild(node)\n if (!initialChild) return {}\n return encodeChildValue(initialChild, getDefaultStateValue(initialChild))\n}\n\nfunction getDefaultSelectionValue(node: StateNodeLike): StateValue {\n if (node.type === 'atomic' || node.type === 'final' || node.type === 'history') {\n return node.key\n }\n\n return getDefaultStateValue(node)\n}\n\nfunction getExistingChildValue(value: unknown, childKey: string): StateValue | undefined {\n if (!value || typeof value !== 'object') return undefined\n return (value as Record<string, StateValue>)[childKey]\n}\n\nfunction getPathToRoot(target: StateNodeLike, root: StateNodeLike): StateNodeLike[] {\n const path: StateNodeLike[] = []\n let current: StateNodeLike | undefined = target\n\n while (current) {\n path.unshift(current)\n if (current.id === root.id) return path\n current = current.parent\n }\n\n throw new Error(`State node '${target.id}' is not part of machine '${root.id}'`)\n}\n\nfunction buildTargetStateValue(\n node: StateNodeLike,\n path: StateNodeLike[],\n currentValue: unknown,\n): StateValue {\n const [, ...restPath] = path\n\n if (restPath.length === 0) {\n if (node.type === 'parallel') {\n const next: Record<string, StateValue> = {}\n for (const child of Object.values(node.states ?? {})) {\n next[child.key] =\n getExistingChildValue(currentValue, child.key) ?? getDefaultSelectionValue(child)\n }\n return next\n }\n\n if (node.type === 'compound') {\n return getDefaultStateValue(node)\n }\n\n return node.key\n }\n\n const child = restPath[0]\n if (node.type === 'parallel') {\n const next: Record<string, StateValue> = {}\n for (const sibling of Object.values(node.states ?? {})) {\n if (sibling.key === child.key) {\n next[sibling.key] = buildTargetStateValue(\n sibling,\n restPath,\n getExistingChildValue(currentValue, sibling.key),\n )\n } else {\n next[sibling.key] =\n getExistingChildValue(currentValue, sibling.key) ?? getDefaultSelectionValue(sibling)\n }\n }\n return next\n }\n\n const childValue = buildTargetStateValue(\n child,\n restPath,\n getExistingChildValue(currentValue, child.key),\n )\n return encodeChildValue(child, childValue)\n}\n\nfunction setActiveState(actorRef: AnyActorRef, stateNodeId: string): void {\n const mutableActorRef = actorRef as MutableActorRef\n const machine = mutableActorRef.logic\n if (\n !machine?.getStateNodeById ||\n !machine.resolveState ||\n typeof mutableActorRef.update !== 'function'\n ) {\n throw new Error('Actor does not expose machine state mutation internals')\n }\n\n const currentSnapshot = actorRef.getSnapshot() as {\n value: unknown\n context?: unknown\n status?: string\n output?: unknown\n error?: unknown\n historyValue?: unknown\n }\n const targetNode = machine.getStateNodeById(stateNodeId)\n const path = getPathToRoot(targetNode, machine.root)\n const targetValue = buildTargetStateValue(machine.root, path, currentSnapshot?.value)\n\n const nextSnapshot = machine.resolveState({\n value: targetValue,\n context: currentSnapshot?.context,\n status: currentSnapshot?.status,\n output: currentSnapshot?.output,\n error: currentSnapshot?.error,\n historyValue: currentSnapshot?.historyValue,\n })\n\n mutableActorRef.update(nextSnapshot, {\n type: 'xstate.devtools.set-active-state',\n stateNodeId,\n })\n}\n\n// Cached on globalThis so HMR re-evaluating this module doesn't reset the\n// monotonic seq counter mid-session. The panel re-numbers messages on ingest\n// to merge multiple sources, but keeping a stable per-process seq still helps\n// when the panel reconnects to an already-running adapter.\nconst SEQ_KEY = '__xstate_devtools_global_seq__'\nfunction nextSeq(): number {\n const g = globalThis as Record<string, unknown>\n const cur = (g[SEQ_KEY] as number | undefined) ?? 0\n const next = cur + 1\n g[SEQ_KEY] = next\n return next\n}\n\nexport function createInspector(\n transport: Transport,\n source: Source,\n options: InspectorOptions = {},\n) {\n const actorRefs = new Map<string, AnyActorRef>()\n const actorMachines = new Map<string, SerializedMachine | null>()\n const prefix = `${source}:`\n const tag = (sessionId: string) => prefix + sessionId\n const tagOptional = (id: string | undefined) => (id ? prefix + id : undefined)\n const stripIfMine = (id: string): string | null =>\n id.startsWith(prefix) ? id.slice(prefix.length) : null\n\n function checkAndNotifyStop(actorRef: AnyActorRef) {\n let snap: any\n try {\n snap = actorRef.getSnapshot()\n } catch {\n return\n }\n if (snap?.status !== 'active') {\n const message: PageToExtensionMessage = {\n type: 'XSTATE_ACTOR_STOPPED',\n sessionId: tag(actorRef.sessionId),\n }\n debugLog(source, 'actor stopped; notifying transport', summarizeMessage(message))\n transport.send(message)\n actorRefs.delete(actorRef.sessionId)\n actorMachines.delete(actorRef.sessionId)\n }\n }\n\n const unsubscribe = transport.subscribe((message) => {\n debugLog(source, 'received message from transport', summarizeMessage(message))\n if (message.type === 'XSTATE_PANEL_CONNECTED') {\n // The devtools panel just connected (or reconnected). Re-broadcast every\n // currently-active actor so the panel is never blank because the MV3\n // service worker was killed between page load and panel open.\n infoLog(source, 'panel connected; resyncing actors', { actorCount: actorRefs.size })\n actorRefs.forEach((actorRef, sessionId) => {\n const machine = actorMachines.get(sessionId) ?? null\n const resyncMessage: PageToExtensionMessage = {\n type: 'XSTATE_ACTOR_REGISTERED',\n sessionId: tag(sessionId),\n parentSessionId: tagOptional((actorRef as any)._parent?.sessionId),\n displayName: getActorDisplayName(actorRef),\n machine,\n snapshot: safeSerializeSnapshot(actorRef),\n globalSeq: nextSeq(),\n timestamp: Date.now(),\n }\n debugLog(source, 'resyncing actor', summarizeMessage(resyncMessage))\n transport.send(resyncMessage)\n })\n return\n }\n if (message.type === 'XSTATE_DISPATCH') {\n const local = stripIfMine(message.sessionId)\n if (local === null) {\n debugLog(source, 'ignoring dispatch for different source', summarizeMessage(message))\n return // not for this transport source\n }\n const ref = actorRefs.get(local)\n if (ref) {\n try {\n debugLog(source, 'dispatching event to actor', {\n sessionId: local,\n eventType:\n message.event && typeof message.event === 'object' && 'type' in message.event\n ? message.event.type\n : undefined,\n })\n ref.send(message.event)\n } catch (e) {\n warnLog(source, 'dispatch error', { error: e, sessionId: local })\n }\n } else {\n warnLog(source, 'received dispatch for unknown actor', {\n sessionId: local,\n knownActors: actorRefs.size,\n })\n }\n return\n }\n if (message.type === 'XSTATE_SET_ACTIVE_STATE') {\n const local = stripIfMine(message.sessionId)\n if (local === null) {\n debugLog(\n source,\n 'ignoring state activation for different source',\n summarizeMessage(message),\n )\n return\n }\n\n const ref = actorRefs.get(local)\n if (!ref) {\n warnLog(source, 'received state activation for unknown actor', {\n sessionId: local,\n knownActors: actorRefs.size,\n })\n return\n }\n\n try {\n debugLog(source, 'setting active state on actor', summarizeMessage(message))\n setActiveState(ref, message.stateNodeId)\n const snapshotMessage: PageToExtensionMessage = {\n type: 'XSTATE_SNAPSHOT',\n sessionId: tag(local),\n snapshot: safeSerializeSnapshot(ref),\n timestamp: Date.now(),\n globalSeq: nextSeq(),\n }\n debugLog(\n source,\n 'sending snapshot after state activation',\n summarizeMessage(snapshotMessage),\n )\n transport.send(snapshotMessage)\n } catch (error) {\n warnLog(source, 'failed to set active state', {\n error,\n sessionId: local,\n stateNodeId: message.stateNodeId,\n })\n }\n }\n })\n\n // Notify the extension that the adapter is ready\n transport.send({ type: 'XSTATE_ADAPTER_READY' })\n\n infoLog(source, 'inspector created')\n\n const inspect = (inspectionEvent: any) => {\n debugLog(source, 'inspect callback invoked', summarizeInspectionEvent(inspectionEvent))\n if (inspectionEvent.type === '@xstate.actor') {\n const actorRef: AnyActorRef = inspectionEvent.actorRef\n const sessionId: string = actorRef.sessionId\n\n // Serialize machine and populate both Maps BEFORE subscribing so that\n // the Maps are fully consistent if complete()/error() ever fire\n // synchronously during subscribe() (e.g. an actor that starts in a\n // final state). Populating after subscribe introduced a race where\n // actorMachines.delete() in the callback was a no-op and the subsequent\n // actorMachines.set() would leak the entry permanently.\n const actorLogic = (actorRef as { logic?: unknown }).logic as any\n const machine = actorLogic?.root\n ? serializeMachine(\n actorLogic,\n actorLogic.config?.__xstateDevtoolsSource ?? getSourceLocation(source, options),\n )\n : null\n actorRefs.set(sessionId, actorRef)\n actorMachines.set(sessionId, machine)\n\n // Eagerly remove the actor from both maps when it stops so we don't\n // accumulate strong references to every short-lived actor indefinitely.\n // Without this, actors that stop silently (no further snapshot/event) are\n // only removed by checkAndNotifyStop — which never fires for them.\n const notifyStop = () => {\n if (actorRefs.has(sessionId)) {\n actorRefs.delete(sessionId)\n actorMachines.delete(sessionId)\n const stopMsg: PageToExtensionMessage = {\n type: 'XSTATE_ACTOR_STOPPED',\n sessionId: tag(sessionId),\n }\n debugLog(source, 'actor stopped; notifying transport', summarizeMessage(stopMsg))\n transport.send(stopMsg)\n }\n }\n try {\n actorRef.subscribe({ complete: notifyStop, error: notifyStop })\n } catch {\n // subscribe is best-effort; older actor implementations may not support it\n }\n\n const message: PageToExtensionMessage = {\n type: 'XSTATE_ACTOR_REGISTERED',\n sessionId: tag(sessionId),\n parentSessionId: tagOptional((actorRef as any)._parent?.sessionId),\n displayName: getActorDisplayName(actorRef),\n machine,\n snapshot: safeSerializeSnapshot(actorRef),\n globalSeq: nextSeq(),\n timestamp: Date.now(),\n }\n infoLog(source, 'registering actor with transport', {\n message: summarizeMessage(message),\n actorCount: actorRefs.size,\n hasMachine: machine !== null,\n })\n transport.send(message)\n } else if (inspectionEvent.type === '@xstate.snapshot') {\n const message: PageToExtensionMessage = {\n type: 'XSTATE_SNAPSHOT',\n sessionId: tag(inspectionEvent.actorRef.sessionId),\n snapshot: serializeSnapshot(inspectionEvent.snapshot),\n timestamp: Date.now(),\n globalSeq: nextSeq(),\n }\n debugLog(source, 'sending snapshot to transport', summarizeMessage(message))\n transport.send(message)\n checkAndNotifyStop(inspectionEvent.actorRef)\n } else if (inspectionEvent.type === '@xstate.event') {\n const message: PageToExtensionMessage = {\n type: 'XSTATE_EVENT',\n sessionId: tag(inspectionEvent.actorRef.sessionId),\n // sanitize() returns unknown; the inspected event keeps its { type, ... }\n // shape, so it is a SerializedEvent after deep-sanitizing.\n event: sanitize(inspectionEvent.event) as SerializedEvent,\n snapshotAfter: safeSerializeSnapshot(inspectionEvent.actorRef),\n timestamp: Date.now(),\n globalSeq: nextSeq(),\n }\n debugLog(source, 'sending event to transport', summarizeMessage(message))\n transport.send(message)\n checkAndNotifyStop(inspectionEvent.actorRef)\n } else {\n debugLog(\n source,\n 'ignoring unsupported inspection event',\n summarizeInspectionEvent(inspectionEvent),\n )\n }\n }\n\n function dispose() {\n infoLog(source, 'disposing inspector', { actorCount: actorRefs.size })\n unsubscribe()\n actorRefs.clear()\n actorMachines.clear()\n }\n\n return { inspect, dispose }\n}\n"],"mappings":"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","names":["debugLog","infoLog","warnLog","child","createTcpServer","summarizeMessage","debugLog","infoLog","warnLog"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
interface ServerAdapterOptions {
|
|
2
|
+
/** Port to listen on. Defaults to env XSTATE_DEVTOOLS_PORT or 9301. */
|
|
3
|
+
port?: number;
|
|
4
|
+
/** Host to bind. Defaults to '127.0.0.1'. */
|
|
5
|
+
host?: string;
|
|
6
|
+
/** Max messages to buffer while no panel is connected. Default 200. */
|
|
7
|
+
bufferSize?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Start a local WebSocket server that the DevTools panel can connect to.
|
|
11
|
+
* Returns the inspector callback. Multiple panels can connect simultaneously.
|
|
12
|
+
*
|
|
13
|
+
* The WS server, connected clients, dispatch handlers, and pre-connection
|
|
14
|
+
* buffer are all stashed on globalThis keyed by port. This makes the function
|
|
15
|
+
* idempotent across HMR re-evaluation: subsequent calls reuse the existing
|
|
16
|
+
* server and only register new inspector hooks.
|
|
17
|
+
*
|
|
18
|
+
* Inspection events emitted before the first panel connects are buffered (up
|
|
19
|
+
* to `bufferSize`, default 200) and flushed to the first connecting client so
|
|
20
|
+
* actors registered at boot are visible.
|
|
21
|
+
*/
|
|
22
|
+
declare function createServerAdapter(options?: ServerAdapterOptions): {
|
|
23
|
+
close: () => void;
|
|
24
|
+
port: Promise<number>;
|
|
25
|
+
inspect: (inspectionEvent: any) => void;
|
|
26
|
+
dispose: () => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { type ServerAdapterOptions, createServerAdapter };
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
interface ServerAdapterOptions {
|
|
2
|
+
/** Port to listen on. Defaults to env XSTATE_DEVTOOLS_PORT or 9301. */
|
|
3
|
+
port?: number;
|
|
4
|
+
/** Host to bind. Defaults to '127.0.0.1'. */
|
|
5
|
+
host?: string;
|
|
6
|
+
/** Max messages to buffer while no panel is connected. Default 200. */
|
|
7
|
+
bufferSize?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Start a local WebSocket server that the DevTools panel can connect to.
|
|
11
|
+
* Returns the inspector callback. Multiple panels can connect simultaneously.
|
|
12
|
+
*
|
|
13
|
+
* The WS server, connected clients, dispatch handlers, and pre-connection
|
|
14
|
+
* buffer are all stashed on globalThis keyed by port. This makes the function
|
|
15
|
+
* idempotent across HMR re-evaluation: subsequent calls reuse the existing
|
|
16
|
+
* server and only register new inspector hooks.
|
|
17
|
+
*
|
|
18
|
+
* Inspection events emitted before the first panel connects are buffered (up
|
|
19
|
+
* to `bufferSize`, default 200) and flushed to the first connecting client so
|
|
20
|
+
* actors registered at boot are visible.
|
|
21
|
+
*/
|
|
22
|
+
declare function createServerAdapter(options?: ServerAdapterOptions): {
|
|
23
|
+
close: () => void;
|
|
24
|
+
port: Promise<number>;
|
|
25
|
+
inspect: (inspectionEvent: any) => void;
|
|
26
|
+
dispose: () => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { type ServerAdapterOptions, createServerAdapter };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createInspector,
|
|
3
|
+
debugLog,
|
|
4
|
+
infoLog,
|
|
5
|
+
sanitize,
|
|
6
|
+
warnLog
|
|
7
|
+
} from "./chunk-3GM2SFT4.js";
|
|
8
|
+
|
|
9
|
+
// src/server.ts
|
|
10
|
+
import { createServer as createTcpServer } from "net";
|
|
11
|
+
function getAvailablePort(start) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const probe = createTcpServer();
|
|
14
|
+
probe.unref();
|
|
15
|
+
probe.on("error", (err) => {
|
|
16
|
+
if (err.code === "EADDRINUSE") {
|
|
17
|
+
resolve(getAvailablePort(start + 1));
|
|
18
|
+
} else {
|
|
19
|
+
reject(err);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
probe.listen(start, "127.0.0.1", () => {
|
|
23
|
+
const port = probe.address().port;
|
|
24
|
+
probe.close(() => resolve(port));
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
var OPEN_STATE = 1;
|
|
29
|
+
function summarizeMessage(message) {
|
|
30
|
+
const summary = { type: message.type };
|
|
31
|
+
if ("sessionId" in message) summary.sessionId = message.sessionId;
|
|
32
|
+
if ("parentSessionId" in message && message.parentSessionId) {
|
|
33
|
+
summary.parentSessionId = message.parentSessionId;
|
|
34
|
+
}
|
|
35
|
+
if ("globalSeq" in message) summary.globalSeq = message.globalSeq;
|
|
36
|
+
if ("timestamp" in message) summary.timestamp = message.timestamp;
|
|
37
|
+
if ("event" in message && message.event && typeof message.event === "object" && "type" in message.event) {
|
|
38
|
+
summary.eventType = message.event.type;
|
|
39
|
+
}
|
|
40
|
+
return summary;
|
|
41
|
+
}
|
|
42
|
+
function debugLog2(message, details) {
|
|
43
|
+
debugLog("server", message, details);
|
|
44
|
+
}
|
|
45
|
+
function infoLog2(message, details) {
|
|
46
|
+
infoLog("server", message, details);
|
|
47
|
+
}
|
|
48
|
+
function warnLog2(message, details) {
|
|
49
|
+
warnLog("server", message, details);
|
|
50
|
+
}
|
|
51
|
+
function stringifyOutgoingMessage(message) {
|
|
52
|
+
const payload = { ...message, __xstateDevtools: true };
|
|
53
|
+
try {
|
|
54
|
+
return JSON.stringify(payload);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
warnLog2("failed to stringify adapter message; retrying with sanitized payload", {
|
|
57
|
+
error,
|
|
58
|
+
message: summarizeMessage(message)
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
return JSON.stringify(sanitize(payload));
|
|
63
|
+
} catch (error) {
|
|
64
|
+
warnLog2("dropping adapter message that could not be stringified", {
|
|
65
|
+
error,
|
|
66
|
+
message: summarizeMessage(message)
|
|
67
|
+
});
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function createServerAdapter(options = {}) {
|
|
72
|
+
const port = options.port ?? (Number(process.env.XSTATE_DEVTOOLS_PORT) || 9301);
|
|
73
|
+
const host = options.host ?? "127.0.0.1";
|
|
74
|
+
const bufferSize = options.bufferSize ?? 200;
|
|
75
|
+
infoLog2("createServerAdapter called", { host, port, bufferSize });
|
|
76
|
+
const key = `__xstate_devtools_server_${port}__`;
|
|
77
|
+
const cache = globalThis[key];
|
|
78
|
+
let server;
|
|
79
|
+
if (cache) {
|
|
80
|
+
server = cache;
|
|
81
|
+
infoLog2("reusing cached WebSocket server", {
|
|
82
|
+
host,
|
|
83
|
+
port,
|
|
84
|
+
clientCount: server.clients.size,
|
|
85
|
+
bufferedMessages: server.buffer.length
|
|
86
|
+
});
|
|
87
|
+
if (bufferSize > server.bufferSize) server.bufferSize = bufferSize;
|
|
88
|
+
} else {
|
|
89
|
+
const clients = /* @__PURE__ */ new Set();
|
|
90
|
+
const dispatchHandlers = /* @__PURE__ */ new Set();
|
|
91
|
+
const buffer = [];
|
|
92
|
+
let wss = null;
|
|
93
|
+
let closed = false;
|
|
94
|
+
let portResolve;
|
|
95
|
+
let portReject;
|
|
96
|
+
const portPromise = new Promise((res, rej) => {
|
|
97
|
+
portResolve = res;
|
|
98
|
+
portReject = rej;
|
|
99
|
+
});
|
|
100
|
+
server = {
|
|
101
|
+
clients,
|
|
102
|
+
dispatchHandlers,
|
|
103
|
+
buffer,
|
|
104
|
+
bufferSize,
|
|
105
|
+
activated: false,
|
|
106
|
+
port: portPromise,
|
|
107
|
+
close: () => {
|
|
108
|
+
closed = true;
|
|
109
|
+
infoLog2("closing WebSocket server", { host, port, clientCount: clients.size });
|
|
110
|
+
try {
|
|
111
|
+
wss?.close();
|
|
112
|
+
} catch {
|
|
113
|
+
}
|
|
114
|
+
clients.clear();
|
|
115
|
+
dispatchHandlers.clear();
|
|
116
|
+
buffer.length = 0;
|
|
117
|
+
delete globalThis[key];
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
void (async () => {
|
|
121
|
+
try {
|
|
122
|
+
const mod = await import("ws");
|
|
123
|
+
const WSServer = mod.WebSocketServer ?? mod.Server;
|
|
124
|
+
if (closed) return;
|
|
125
|
+
const actualPort = await getAvailablePort(port);
|
|
126
|
+
if (closed) return;
|
|
127
|
+
wss = new WSServer({ port: actualPort, host });
|
|
128
|
+
process.env.XSTATE_DEVTOOLS_PORT = String(actualPort);
|
|
129
|
+
portResolve(actualPort);
|
|
130
|
+
infoLog2("WebSocket server listening", { host, port: actualPort });
|
|
131
|
+
wss.on("connection", (ws) => {
|
|
132
|
+
infoLog2("panel connected to WebSocket server", {
|
|
133
|
+
host,
|
|
134
|
+
port,
|
|
135
|
+
activated: server.activated,
|
|
136
|
+
bufferedMessages: server.buffer.length
|
|
137
|
+
});
|
|
138
|
+
if (!server.activated) {
|
|
139
|
+
server.activated = true;
|
|
140
|
+
infoLog2("flushing bootstrap buffer to first panel", {
|
|
141
|
+
host,
|
|
142
|
+
port,
|
|
143
|
+
bufferedMessages: server.buffer.length
|
|
144
|
+
});
|
|
145
|
+
for (const payload of server.buffer) {
|
|
146
|
+
try {
|
|
147
|
+
ws.send(payload);
|
|
148
|
+
} catch {
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
server.buffer.length = 0;
|
|
152
|
+
}
|
|
153
|
+
server.clients.add(ws);
|
|
154
|
+
ws.on("message", (raw) => {
|
|
155
|
+
try {
|
|
156
|
+
const text = typeof raw === "string" ? raw : raw.toString("utf8");
|
|
157
|
+
const msg = JSON.parse(text);
|
|
158
|
+
debugLog2("received dispatch from panel", summarizeMessage(msg));
|
|
159
|
+
for (const cb of server.dispatchHandlers) cb(msg);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
warnLog2("failed to parse panel message", { error });
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
ws.on("close", () => {
|
|
165
|
+
server.clients.delete(ws);
|
|
166
|
+
infoLog2("panel disconnected from WebSocket server", {
|
|
167
|
+
host,
|
|
168
|
+
port,
|
|
169
|
+
clientCount: server.clients.size
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
ws.on("error", (error) => {
|
|
173
|
+
server.clients.delete(ws);
|
|
174
|
+
warnLog2("WebSocket client error", { error });
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
wss.on("error", (err) => {
|
|
178
|
+
warnLog2("WS server error", { host, port, message: err.message });
|
|
179
|
+
});
|
|
180
|
+
} catch (e) {
|
|
181
|
+
portReject(e);
|
|
182
|
+
warnLog2("could not start server adapter \u2014 install `ws` to enable", {
|
|
183
|
+
host,
|
|
184
|
+
port,
|
|
185
|
+
message: e.message
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
})();
|
|
189
|
+
globalThis[key] = server;
|
|
190
|
+
}
|
|
191
|
+
const transport = {
|
|
192
|
+
send(message) {
|
|
193
|
+
const payload = stringifyOutgoingMessage(message);
|
|
194
|
+
if (payload === null) return;
|
|
195
|
+
if (!server.activated) {
|
|
196
|
+
if (server.buffer.length >= server.bufferSize) server.buffer.shift();
|
|
197
|
+
server.buffer.push(payload);
|
|
198
|
+
debugLog2("buffered outgoing adapter message; no panel connected yet", {
|
|
199
|
+
bufferedMessages: server.buffer.length,
|
|
200
|
+
message: summarizeMessage(message)
|
|
201
|
+
});
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
let sentCount = 0;
|
|
205
|
+
for (const ws of server.clients) {
|
|
206
|
+
if (ws.readyState === OPEN_STATE) {
|
|
207
|
+
try {
|
|
208
|
+
ws.send(payload);
|
|
209
|
+
sentCount += 1;
|
|
210
|
+
} catch {
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
debugLog2("sent adapter message to connected panels", {
|
|
215
|
+
sentCount,
|
|
216
|
+
clientCount: server.clients.size,
|
|
217
|
+
message: summarizeMessage(message)
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
subscribe(handler) {
|
|
221
|
+
server.dispatchHandlers.add(handler);
|
|
222
|
+
debugLog2("registered dispatch handler", { handlerCount: server.dispatchHandlers.size });
|
|
223
|
+
return () => {
|
|
224
|
+
server.dispatchHandlers.delete(handler);
|
|
225
|
+
debugLog2("removed dispatch handler", { handlerCount: server.dispatchHandlers.size });
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
const inspector = createInspector(transport, "srv");
|
|
230
|
+
return { ...inspector, close: server.close, port: server.port };
|
|
231
|
+
}
|
|
232
|
+
export {
|
|
233
|
+
createServerAdapter
|
|
234
|
+
};
|
|
235
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["// Server entrypoint — exposes a WebSocket bridge so the DevTools panel\n// can connect to actors running in Node.\nimport { createServer as createTcpServer } from 'node:net'\nimport type {\n ExtensionToPageMessage,\n PageToExtensionMessage,\n} from '../../extension/src/shared/types.js'\nimport { createInspector, type Transport } from './core.js'\nimport {\n debugLog as baseDebugLog,\n infoLog as baseInfoLog,\n warnLog as baseWarnLog,\n} from './logging.js'\nimport { sanitize } from './sanitize.js'\n\n/**\n * Find the lowest TCP port >= `start` that is not currently in use.\n * Uses a temporary TCP server to probe; the port is released before resolving.\n */\nfunction getAvailablePort(start: number): Promise<number> {\n return new Promise((resolve, reject) => {\n const probe = createTcpServer()\n probe.unref()\n probe.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n resolve(getAvailablePort(start + 1))\n } else {\n reject(err)\n }\n })\n probe.listen(start, '127.0.0.1', () => {\n const port = (probe.address() as { port: number }).port\n probe.close(() => resolve(port))\n })\n })\n}\n\nexport interface ServerAdapterOptions {\n /** Port to listen on. Defaults to env XSTATE_DEVTOOLS_PORT or 9301. */\n port?: number\n /** Host to bind. Defaults to '127.0.0.1'. */\n host?: string\n /** Max messages to buffer while no panel is connected. Default 200. */\n bufferSize?: number\n}\n\ninterface ClientLike {\n send(data: string): void\n on(event: string, listener: (...args: unknown[]) => void): void\n readyState: number\n}\n\nconst OPEN_STATE = 1\n\nfunction summarizeMessage(message: ExtensionToPageMessage | PageToExtensionMessage) {\n const summary: Record<string, unknown> = { type: message.type }\n if ('sessionId' in message) summary.sessionId = message.sessionId\n if ('parentSessionId' in message && message.parentSessionId) {\n summary.parentSessionId = message.parentSessionId\n }\n if ('globalSeq' in message) summary.globalSeq = message.globalSeq\n if ('timestamp' in message) summary.timestamp = message.timestamp\n if (\n 'event' in message &&\n message.event &&\n typeof message.event === 'object' &&\n 'type' in message.event\n ) {\n summary.eventType = message.event.type\n }\n return summary\n}\n\nfunction debugLog(message: string, details?: unknown) {\n baseDebugLog('server', message, details)\n}\n\nfunction infoLog(message: string, details?: unknown) {\n baseInfoLog('server', message, details)\n}\n\nfunction warnLog(message: string, details?: unknown) {\n baseWarnLog('server', message, details)\n}\n\nfunction stringifyOutgoingMessage(message: PageToExtensionMessage): string | null {\n const payload = { ...message, __xstateDevtools: true as const }\n\n try {\n return JSON.stringify(payload)\n } catch (error) {\n warnLog('failed to stringify adapter message; retrying with sanitized payload', {\n error,\n message: summarizeMessage(message),\n })\n }\n\n try {\n return JSON.stringify(sanitize(payload))\n } catch (error) {\n warnLog('dropping adapter message that could not be stringified', {\n error,\n message: summarizeMessage(message),\n })\n return null\n }\n}\n\ninterface CachedServer {\n clients: Set<ClientLike>\n dispatchHandlers: Set<(msg: ExtensionToPageMessage) => void>\n buffer: string[]\n bufferSize: number\n activated: boolean\n /** Resolves with the actual TCP port once the WS server is listening. */\n port: Promise<number>\n close: () => void\n}\n\n/**\n * Start a local WebSocket server that the DevTools panel can connect to.\n * Returns the inspector callback. Multiple panels can connect simultaneously.\n *\n * The WS server, connected clients, dispatch handlers, and pre-connection\n * buffer are all stashed on globalThis keyed by port. This makes the function\n * idempotent across HMR re-evaluation: subsequent calls reuse the existing\n * server and only register new inspector hooks.\n *\n * Inspection events emitted before the first panel connects are buffered (up\n * to `bufferSize`, default 200) and flushed to the first connecting client so\n * actors registered at boot are visible.\n */\nexport function createServerAdapter(options: ServerAdapterOptions = {}) {\n const port = options.port ?? (Number(process.env.XSTATE_DEVTOOLS_PORT) || 9301)\n const host = options.host ?? '127.0.0.1'\n const bufferSize = options.bufferSize ?? 200\n infoLog('createServerAdapter called', { host, port, bufferSize })\n\n const key = `__xstate_devtools_server_${port}__`\n const cache = (globalThis as Record<string, unknown>)[key] as CachedServer | undefined\n\n let server: CachedServer\n if (cache) {\n server = cache\n infoLog('reusing cached WebSocket server', {\n host,\n port,\n clientCount: server.clients.size,\n bufferedMessages: server.buffer.length,\n })\n // honour the most recent caller's buffer size if larger\n if (bufferSize > server.bufferSize) server.bufferSize = bufferSize\n } else {\n const clients = new Set<ClientLike>()\n const dispatchHandlers = new Set<(msg: ExtensionToPageMessage) => void>()\n const buffer: string[] = []\n let wss: any = null\n let closed = false\n\n let portResolve!: (port: number) => void\n let portReject!: (err: unknown) => void\n const portPromise = new Promise<number>((res, rej) => {\n portResolve = res\n portReject = rej\n })\n\n server = {\n clients,\n dispatchHandlers,\n buffer,\n bufferSize,\n activated: false,\n port: portPromise,\n close: () => {\n closed = true\n infoLog('closing WebSocket server', { host, port, clientCount: clients.size })\n try {\n wss?.close()\n } catch {\n /* noop */\n }\n clients.clear()\n dispatchHandlers.clear()\n buffer.length = 0\n delete (globalThis as Record<string, unknown>)[key]\n },\n }\n\n // Lazily import ws so this module is import-safe in environments that\n // never use the server entrypoint (or where ws isn't installed).\n void (async () => {\n try {\n const mod = await import('ws')\n const WSServer = (mod as any).WebSocketServer ?? (mod as any).Server\n if (closed) return\n const actualPort = await getAvailablePort(port)\n if (closed) return\n wss = new WSServer({ port: actualPort, host })\n process.env.XSTATE_DEVTOOLS_PORT = String(actualPort)\n portResolve(actualPort)\n infoLog('WebSocket server listening', { host, port: actualPort })\n wss.on('connection', (ws: ClientLike) => {\n infoLog('panel connected to WebSocket server', {\n host,\n port,\n activated: server.activated,\n bufferedMessages: server.buffer.length,\n })\n // Drain bootstrap buffer to the first client only.\n if (!server.activated) {\n server.activated = true\n infoLog('flushing bootstrap buffer to first panel', {\n host,\n port,\n bufferedMessages: server.buffer.length,\n })\n for (const payload of server.buffer) {\n try {\n ws.send(payload)\n } catch {\n /* ignore */\n }\n }\n server.buffer.length = 0\n }\n server.clients.add(ws)\n ws.on('message', (raw: unknown) => {\n try {\n const text = typeof raw === 'string' ? raw : (raw as Buffer).toString('utf8')\n const msg = JSON.parse(text) as ExtensionToPageMessage\n debugLog('received dispatch from panel', summarizeMessage(msg))\n for (const cb of server.dispatchHandlers) cb(msg)\n } catch (error) {\n warnLog('failed to parse panel message', { error })\n }\n })\n ws.on('close', () => {\n server.clients.delete(ws)\n infoLog('panel disconnected from WebSocket server', {\n host,\n port,\n clientCount: server.clients.size,\n })\n })\n ws.on('error', (error: unknown) => {\n server.clients.delete(ws)\n warnLog('WebSocket client error', { error })\n })\n })\n wss.on('error', (err: Error) => {\n warnLog('WS server error', { host, port, message: err.message })\n })\n } catch (e) {\n portReject(e)\n warnLog('could not start server adapter — install `ws` to enable', {\n host,\n port,\n message: (e as Error).message,\n })\n }\n })()\n\n ;(globalThis as Record<string, unknown>)[key] = server\n }\n\n const transport: Transport = {\n send(message: PageToExtensionMessage) {\n const payload = stringifyOutgoingMessage(message)\n if (payload === null) return\n\n if (!server.activated) {\n // No panel has connected yet — buffer for the first one.\n if (server.buffer.length >= server.bufferSize) server.buffer.shift()\n server.buffer.push(payload)\n debugLog('buffered outgoing adapter message; no panel connected yet', {\n bufferedMessages: server.buffer.length,\n message: summarizeMessage(message),\n })\n return\n }\n let sentCount = 0\n for (const ws of server.clients) {\n if (ws.readyState === OPEN_STATE) {\n try {\n ws.send(payload)\n sentCount += 1\n } catch {\n /* ignore */\n }\n }\n }\n debugLog('sent adapter message to connected panels', {\n sentCount,\n clientCount: server.clients.size,\n message: summarizeMessage(message),\n })\n },\n subscribe(handler) {\n server.dispatchHandlers.add(handler)\n debugLog('registered dispatch handler', { handlerCount: server.dispatchHandlers.size })\n return () => {\n server.dispatchHandlers.delete(handler)\n debugLog('removed dispatch handler', { handlerCount: server.dispatchHandlers.size })\n }\n },\n }\n\n const inspector = createInspector(transport, 'srv')\n return { ...inspector, close: server.close, port: server.port }\n}\n"],"mappings":"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","names":["debugLog","infoLog","warnLog"]}
|
package/package.json
CHANGED
|
@@ -1,21 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xstate-devtools/adapter",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Inspect XState v5 actors from a running app (browser, Node/SSR, or React) and stream them to the XState DevTools / VS Code live debugger.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/mjbeswick/xstate-devtools.git",
|
|
9
|
+
"directory": "packages/adapter"
|
|
10
|
+
},
|
|
11
|
+
"keywords": ["xstate", "statechart", "devtools", "inspector", "debugger"],
|
|
4
12
|
"type": "module",
|
|
5
|
-
"main": "./
|
|
13
|
+
"main": "./dist/index.cjs",
|
|
14
|
+
"module": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
6
16
|
"exports": {
|
|
7
|
-
".":
|
|
8
|
-
|
|
9
|
-
|
|
17
|
+
".": {
|
|
18
|
+
"development": "./src/index.ts",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"import": "./dist/index.js",
|
|
21
|
+
"require": "./dist/index.cjs"
|
|
22
|
+
},
|
|
23
|
+
"./server": {
|
|
24
|
+
"development": "./src/server.ts",
|
|
25
|
+
"types": "./dist/server.d.ts",
|
|
26
|
+
"import": "./dist/server.js",
|
|
27
|
+
"require": "./dist/server.cjs"
|
|
28
|
+
},
|
|
29
|
+
"./react": {
|
|
30
|
+
"development": "./src/react.tsx",
|
|
31
|
+
"types": "./dist/react.d.ts",
|
|
32
|
+
"import": "./dist/react.js",
|
|
33
|
+
"require": "./dist/react.cjs"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": ["dist"],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18"
|
|
10
39
|
},
|
|
11
40
|
"scripts": {
|
|
12
|
-
"
|
|
41
|
+
"build": "tsup",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"prepublishOnly": "npm run build"
|
|
13
44
|
},
|
|
14
45
|
"peerDependencies": {
|
|
46
|
+
"@xstate/react": "^4.0.0",
|
|
47
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
15
48
|
"ws": "^8.0.0",
|
|
16
49
|
"xstate": "^5.0.0"
|
|
17
50
|
},
|
|
18
51
|
"peerDependenciesMeta": {
|
|
52
|
+
"@xstate/react": {
|
|
53
|
+
"optional": true
|
|
54
|
+
},
|
|
55
|
+
"react": {
|
|
56
|
+
"optional": true
|
|
57
|
+
},
|
|
19
58
|
"ws": {
|
|
20
59
|
"optional": true
|
|
21
60
|
}
|
|
@@ -25,6 +64,7 @@
|
|
|
25
64
|
"@types/ws": "^8.18.1",
|
|
26
65
|
"@xstate/react": "^4.1.0",
|
|
27
66
|
"react": "^18.3.0",
|
|
67
|
+
"tsup": "^8.0.0",
|
|
28
68
|
"typescript": "^5.5.0",
|
|
29
69
|
"vitest": "^2.0.0",
|
|
30
70
|
"ws": "^8.20.0",
|