@dxfeed/dxlink-console-rpc 0.0.0-stage → 0.10.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/plugin.tsx","../src/descriptors.ts","../src/rpc-channel.tsx","../src/rpc-view-model.ts","../src/rpc-channel-request.tsx"],"sourcesContent":["/**\n * The RPC channel service: call a method of a protobuf service over a dxLink channel.\n *\n * Deliberately does not export the channel body or the request form — a host registers the\n * plugin and the core renders what it names.\n */\nexport { rpcChannelPlugin } from './plugin'\nexport type { RpcChannelPluginOptions } from './plugin'\nexport type { RpcConfig, RpcRequest } from './types'\n","import { defineChannelPlugin } from '@dxfeed/dxlink-console-core'\nimport SwapHorizIcon from '@mui/icons-material/SwapHoriz'\n\nimport { parseRequest } from './descriptors'\nimport { RpcChannel } from './rpc-channel'\nimport { canOpenRpcChannel, RpcChannelRequest } from './rpc-channel-request'\nimport type { RpcConfig, RpcRequest } from './types'\n\nexport interface RpcChannelPluginOptions {\n /**\n * Descriptor-set endpoint the request form starts with.\n *\n * Supplied at composition rather than read from the console profile, which is why neither\n * the channels area nor the profile has to know that descriptor sets exist.\n */\n descriptorSetUrl?: string\n /**\n * Pin that endpoint: the field renders read-only, as a locked WebSocket URL does.\n *\n * Belongs here rather than in the profile's `locked` list for the same reason as the URL\n * itself — it is this service's setting, and core has no vocabulary for it.\n */\n locked?: boolean\n}\n\n/** The RPC service: call a method from a protobuf descriptor set. */\nexport const rpcChannelPlugin = ({\n descriptorSetUrl = '',\n locked = false,\n}: RpcChannelPluginOptions = {}) =>\n defineChannelPlugin<RpcConfig, RpcRequest>({\n kind: 'rpc',\n label: 'RPC',\n icon: <SwapHorizIcon />,\n dialogTitle: 'New RPC channel',\n // A service picker, a method picker and a JSON editor; the other three forms are a\n // handful of fields.\n dialogMaxWidth: 'md',\n createRequest: () => ({\n url: descriptorSetUrl,\n registry: null,\n source: null,\n serviceName: '',\n methodName: '',\n json: '{}',\n }),\n RequestForm: ({ value, onChange }) => (\n <RpcChannelRequest value={value} onChange={onChange} urlLocked={locked} />\n ),\n canOpen: canOpenRpcChannel,\n buildConfig: (request) => {\n const service = request.registry?.getService(request.serviceName)\n const method = service?.method[request.methodName]\n if (service === undefined || method === undefined) {\n return null\n }\n const parsed = parseRequest(method.input, request.json)\n\n return 'error' in parsed ? null : { service, method, request: parsed.message }\n },\n Channel: RpcChannel,\n })\n","import {\n createFileRegistry,\n type DescField,\n type DescMessage,\n type DescMethod,\n type DescService,\n type FileRegistry,\n fromBinary,\n fromJson,\n type JsonValue,\n type Message,\n ScalarType,\n toJson,\n} from '@bufbuild/protobuf'\nimport { protoCamelCase } from '@bufbuild/protobuf/reflect'\nimport { type FileDescriptorSet, FileDescriptorSetSchema } from '@bufbuild/protobuf/wkt'\n\n/**\n * Reading protobuf service definitions at runtime.\n *\n * The console is given a `FileDescriptorSet` — fetched from an endpoint, or picked from\n * disk — and builds a registry from it in the browser. The `DescService` descriptors that\n * come out are structurally what generated code produces, so `createDXLinkDynamicService`\n * consumes them directly.\n */\n\n/** Interaction model of a method, as the dxLink protocol names it. */\nexport interface MethodModel {\n label: string\n /** Whether the dxLink v1.0 wire can carry it. */\n supported: boolean\n description: string\n}\n\nexport const METHOD_MODELS: Record<DescMethod['methodKind'], MethodModel> = {\n unary: {\n label: 'REQUEST_RESPONSE',\n supported: true,\n description: 'One request, one response.',\n },\n server_streaming: {\n label: 'REQUEST_STREAM',\n supported: true,\n description: 'One request, a stream of responses.',\n },\n bidi_streaming: {\n label: 'STREAM_STREAM',\n supported: true,\n description: 'A stream of requests, a stream of responses.',\n },\n client_streaming: {\n label: 'STREAM_RESPONSE',\n supported: false,\n description:\n 'Not supported — the dxLink v1.0 wire has no graceful request half-close, so the server is never told the requests ended.',\n },\n}\n\nexport const methodModel = (method: DescMethod): MethodModel => METHOD_MODELS[method.methodKind]\n\nexport const isMethodSupported = (method: DescMethod): boolean => methodModel(method).supported\n\n/**\n * Decode a descriptor set, accepting either the binary wire format (`buf build -o set.binpb`)\n * or protobuf-JSON. Which one an endpoint serves is its own choice, and a debug console\n * should not care.\n */\nconst decodeDescriptorSet = (bytes: Uint8Array): FileDescriptorSet => {\n const firstByte = bytes.find((byte) => byte > 0x20)\n\n // '{' — protobuf-JSON. Binary descriptor sets start with a field tag (0x0a for `file`),\n // so sniffing the first non-whitespace byte separates them without guessing.\n if (firstByte === 0x7b) {\n return fromJson(FileDescriptorSetSchema, JSON.parse(new TextDecoder().decode(bytes)))\n }\n\n return fromBinary(FileDescriptorSetSchema, bytes)\n}\n\n/**\n * Fill in the JSON name of every field whose descriptor omits it.\n *\n * `json_name` is optional on the wire and is meant to be deduced from the field name when\n * absent, but protobuf-es assigns it straight through, so a descriptor set without it leaves\n * every field reporting an empty JSON name. Encoding then puts each field of a message under\n * the same `\"\"` key and all but the last is lost; decoding rejects the real names.\n *\n * dxLink's own `/proto/docs` serves such a set — only the bundled `google/protobuf/*` files\n * carry `json_name` — so this is repaired here rather than left to the server. The deduction is\n * protobuf's own, via the `protoCamelCase` protobuf-es uses for the same purpose elsewhere.\n *\n * Mutating descriptors is safe here and nowhere else: the registry was just built from these\n * bytes and nothing else has seen it yet. Extension fields are left alone — their JSON name is\n * the bracketed type name, not a deduction.\n */\nconst deduceMissingJsonNames = (registry: FileRegistry): FileRegistry => {\n for (const desc of registry) {\n if (desc.kind !== 'message') continue\n for (const field of desc.fields) {\n if (field.jsonName === '') {\n // The descriptor types are readonly, which is right for every other consumer.\n ;(field as { jsonName: string }).jsonName = protoCamelCase(field.name)\n }\n }\n }\n\n return registry\n}\n\n/** Build a registry from the bytes of a `FileDescriptorSet`. */\nexport const parseDescriptorSet = (bytes: Uint8Array): FileRegistry =>\n deduceMissingJsonNames(createFileRegistry(decodeDescriptorSet(bytes)))\n\n/**\n * Media types that ask a schema endpoint for the binary representation.\n *\n * dxLink's `/proto/docs` negotiates on `Accept` and serves protobuf-JSON to everything else —\n * including the wildcard a fetch sends by default, which matches JSON. Asking explicitly\n * roughly halves the payload. There is deliberately no wildcard in the list: the server takes\n * the first media type that matches, and a wildcard would match JSON first.\n */\nconst BINARY_ACCEPT = 'application/protobuf, application/x-protobuf, application/octet-stream'\n\n/** Fetch a `FileDescriptorSet` from an endpoint and build a registry from it. */\nexport const fetchDescriptorSet = async (url: string): Promise<FileRegistry> => {\n let response: Response\n try {\n response = await fetch(url, { headers: { Accept: BINARY_ACCEPT } })\n } catch (error) {\n // Browsers report every blocked cross-origin request as an opaque network error. Naming\n // the likely cause saves the next person a session in the network tab — and note that\n // asking for a media type makes the request preflighted, so an endpoint on another origin\n // has to allow the `Accept` header as well as the origin itself.\n throw new Error(\n 'the endpoint must be reachable, and one on another origin must allow cross-origin ' +\n 'requests including the Accept header',\n { cause: error }\n )\n }\n\n if (!response.ok) {\n throw new Error(`${response.status} ${response.statusText}`)\n }\n\n return parseDescriptorSet(new Uint8Array(await response.arrayBuffer()))\n}\n\n/** Build a registry from a descriptor set the user picked from disk. */\nexport const readDescriptorSet = async (file: File): Promise<FileRegistry> =>\n parseDescriptorSet(new Uint8Array(await file.arrayBuffer()))\n\n/** Every service in a registry, ordered by fully qualified name. */\nexport const listServices = (registry: FileRegistry): DescService[] => {\n const services: DescService[] = []\n for (const desc of registry) {\n if (desc.kind === 'service') {\n services.push(desc)\n }\n }\n\n return services.sort((a, b) => a.typeName.localeCompare(b.typeName))\n}\n\n/**\n * A protobuf-JSON placeholder for a field, so the request editor opens on the shape of the\n * message rather than on `{}`. Canonical protobuf-JSON is what goes on the wire, so what the\n * user edits is what is sent — 64-bit integers as strings, bytes as base64, enums by name.\n */\nconst fieldTemplate = (field: DescField): JsonValue => {\n switch (field.fieldKind) {\n case 'list':\n return []\n case 'map':\n return {}\n case 'message':\n return {}\n case 'enum':\n return field.enum.values[0]?.name ?? 0\n case 'scalar':\n switch (field.scalar) {\n case ScalarType.BOOL:\n return false\n case ScalarType.STRING:\n case ScalarType.BYTES:\n return ''\n case ScalarType.INT64:\n case ScalarType.UINT64:\n case ScalarType.FIXED64:\n case ScalarType.SFIXED64:\n case ScalarType.SINT64:\n return '0'\n default:\n return 0\n }\n }\n}\n\n/** A protobuf-JSON skeleton of a request message, one entry per declared field. */\nexport const createRequestTemplate = (message: DescMessage): Record<string, JsonValue> =>\n Object.fromEntries(message.fields.map((field) => [field.jsonName, fieldTemplate(field)]))\n\n/**\n * Parse a request message from the protobuf-JSON in the editor.\n *\n * `fromJson` is the validation: it rejects unknown fields and wrong types, which is exactly\n * what a request form needs to report before a channel is opened.\n */\nexport const parseRequest = (\n message: DescMessage,\n json: string\n): { message: Message } | { error: string } => {\n let parsed: unknown\n try {\n parsed = JSON.parse(json)\n } catch (error) {\n return { error: `Invalid JSON: ${error instanceof Error ? error.message : String(error)}` }\n }\n\n try {\n return { message: fromJson(message, parsed as JsonValue) }\n } catch (error) {\n return { error: error instanceof Error ? error.message : String(error) }\n }\n}\n\n/** Canonical protobuf-JSON of a message — what the binding puts on the wire. */\nexport const formatMessage = (schema: DescMessage, message: Message): JsonValue =>\n toJson(schema, message)\n","import { useVM } from '@dxfeed/dxlink-console-core'\nimport { ChannelWidget } from '@dxfeed/dxlink-console-core'\nimport { useConnectionVM } from '@dxfeed/dxlink-console-core'\nimport SendIcon from '@mui/icons-material/Send'\nimport SwapHorizIcon from '@mui/icons-material/SwapHoriz'\nimport Alert from '@mui/material/Alert'\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Chip from '@mui/material/Chip'\nimport Paper from '@mui/material/Paper'\nimport Stack from '@mui/material/Stack'\nimport TextField from '@mui/material/TextField'\nimport Typography from '@mui/material/Typography'\nimport { useEffect, useState } from 'react'\n\nimport { createRequestTemplate, methodModel, parseRequest } from './descriptors'\nimport { RpcViewModel } from './rpc-view-model'\nimport type { RpcCallState, RpcMessageEntry } from './rpc-view-model'\nimport type { RpcConfig } from './types'\n\ninterface RpcChannelProps {\n title: string\n config: RpcConfig\n}\n\nconst RpcStatusChip = ({ state, responses }: { state: RpcCallState; responses: number }) => {\n if (state === 'failed') {\n return <Chip size=\"small\" color=\"error\" variant=\"outlined\" label=\"failed\" />\n }\n if (state === 'completed') {\n return <Chip size=\"small\" variant=\"outlined\" label=\"completed\" />\n }\n\n return responses === 0 ? (\n <Chip size=\"small\" color=\"warning\" variant=\"outlined\" label=\"waiting\" />\n ) : (\n <Chip size=\"small\" color=\"success\" variant=\"outlined\" label=\"streaming\" />\n )\n}\n\n/** One exchanged message, as the protobuf-JSON that crossed the wire. */\nconst MessageEntry = ({ entry }: { entry: RpcMessageEntry }) => (\n <Paper variant=\"outlined\" sx={{ p: 1.5 }}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {entry.time}\n </Typography>\n <Box\n component=\"pre\"\n sx={{ m: 0, mt: 0.5, fontSize: 13, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}\n >\n {JSON.stringify(entry.json, null, 2)}\n </Box>\n </Paper>\n)\n\nconst MessageList = ({\n title,\n entries,\n empty,\n}: {\n title: string\n entries: readonly RpcMessageEntry[]\n empty: string\n}) => (\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'baseline' }}>\n <Typography variant=\"subtitle2\">{title}</Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {entries.length}\n </Typography>\n </Stack>\n {entries.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {empty}\n </Typography>\n ) : (\n entries.map((entry) => <MessageEntry key={entry.id} entry={entry} />)\n )}\n </Stack>\n)\n\n/**\n * Send box for a bidirectional call — the only model where the client keeps talking after\n * the channel is open.\n */\nconst SendRequest = ({\n vm,\n config,\n active,\n}: {\n vm: RpcViewModel\n config: RpcConfig\n /** False once the call has completed or failed — the channel is gone, nothing can be sent. */\n active: boolean\n}) => {\n const [json, setJson] = useState(() =>\n JSON.stringify(createRequestTemplate(config.method.input), null, 2)\n )\n const parsed = parseRequest(config.method.input, json)\n\n return (\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">Send another request</Typography>\n <TextField\n value={json}\n onChange={(e) => setJson(e.target.value)}\n multiline\n minRows={4}\n fullWidth\n size=\"small\"\n slotProps={{ input: { sx: { fontFamily: 'monospace', fontSize: 13 } } }}\n />\n {'error' in parsed && <Alert severity=\"error\">{parsed.error}</Alert>}\n <Box>\n <Button\n variant=\"contained\"\n startIcon={<SendIcon />}\n disabled={!active || 'error' in parsed}\n onClick={() => {\n if ('message' in parsed) vm.send(parsed.message)\n }}\n >\n Send\n </Button>\n </Box>\n </Stack>\n )\n}\n\n/** Live RPC channel — one method of a protobuf service, bound to the connection. */\nexport const RpcChannel = ({ title, config }: RpcChannelProps) => {\n const connectionVM = useConnectionVM()\n const [vm] = useState(() => {\n const client = connectionVM.getClient()\n if (client === null) {\n throw new Error('RPC channel opened without an active connection')\n }\n\n return new RpcViewModel(client, {\n service: config.service,\n method: config.method,\n request: config.request,\n })\n })\n useEffect(() => {\n vm.start()\n return () => vm.stop()\n }, [vm])\n\n const callState = useVM(vm, (s) => s.callState)\n const responses = useVM(vm, (s) => s.responses)\n const requests = useVM(vm, (s) => s.requests)\n const errors = useVM(vm, (s) => s.errors)\n\n const model = methodModel(config.method)\n\n return (\n <ChannelWidget\n icon={<SwapHorizIcon />}\n title={title}\n subtitle={`${config.service.typeName} · ${config.method.name}`}\n onClose={vm.close}\n status={<RpcStatusChip state={callState} responses={responses.length} />}\n // The channel is opened inside the RPC transport, so its protocol id is not exposed\n // here; the parameters are the ones `DxLinkRpcService` opens it with.\n parameters={{ service: config.service.typeName, methodName: config.method.name }}\n errors={errors}\n onClearErrors={vm.clearErrors}\n >\n <Stack spacing={2}>\n <Stack direction=\"row\" spacing={0.5} useFlexGap sx={{ flexWrap: 'wrap' }}>\n <Chip size=\"small\" variant=\"outlined\" label={model.label} />\n <Chip size=\"small\" variant=\"outlined\" label={`in: ${config.method.input.typeName}`} />\n <Chip size=\"small\" variant=\"outlined\" label={`out: ${config.method.output.typeName}`} />\n </Stack>\n\n {vm.isBidirectional && (\n <SendRequest vm={vm} config={config} active={callState === 'active'} />\n )}\n\n <MessageList title=\"Sent\" entries={requests} empty=\"Nothing sent yet.\" />\n <MessageList\n title=\"Received\"\n entries={responses}\n empty={\n callState === 'completed'\n ? 'The server closed the channel without a response.'\n : 'Waiting for the first response…'\n }\n />\n </Stack>\n </ChannelWidget>\n )\n}\n","import type { DescMethod, DescService, JsonValue, Message } from '@bufbuild/protobuf'\nimport type { DXLinkClient, DXLinkError } from '@dxfeed/dxlink-api'\nimport { DXLinkLogLevel } from '@dxfeed/dxlink-api'\nimport { prependError } from '@dxfeed/dxlink-console-core'\nimport type { TimestampedError } from '@dxfeed/dxlink-console-core'\nimport type { ViewModel } from '@dxfeed/dxlink-console-core'\nimport { createDXLinkDynamicService } from '@dxfeed/dxlink-protobuf-es'\nimport { ReplaySubject, type Subscription } from 'rxjs'\nimport { createStore } from 'zustand/vanilla'\n\nimport { formatMessage } from './descriptors'\n\n/** One message exchanged on the call, kept as the protobuf-JSON that went over the wire. */\nexport interface RpcMessageEntry {\n /** Stable identity for React keys — entries are prepended. */\n id: number\n time: string\n json: JsonValue\n}\n\nexport type RpcCallState = 'active' | 'completed' | 'failed'\n\nexport interface RpcVMState {\n callState: RpcCallState\n /** Responses received, newest first. */\n responses: RpcMessageEntry[]\n /** Requests sent, newest first. More than one only for bidirectional methods. */\n requests: RpcMessageEntry[]\n errors: TimestampedError[]\n}\n\n// Coalesce responses arriving within this window into one store update (~10fps).\nconst FLUSH_INTERVAL_MS = 100\n\n/**\n * How many responses one call retains. A streaming RPC left open produces an unbounded\n * number of them, and only the most recent are useful in a console.\n */\nexport const MAX_RESPONSES = 200\n\nlet lastEntryId = 0\n\nconst entry = (json: JsonValue): RpcMessageEntry => {\n lastEntryId += 1\n\n return { id: lastEntryId, time: new Date().toLocaleTimeString(), json }\n}\n\n/**\n * The interaction models carry errors differently from the other services: there is no\n * channel object to listen on, the failure arrives on the Observable. A `DXLinkError` from\n * the server is forwarded as-is; anything else (a decode failure, say) is reported as UNKNOWN.\n */\nconst toDXLinkError = (error: unknown): DXLinkError => {\n if (\n typeof error === 'object' &&\n error !== null &&\n 'type' in error &&\n 'message' in error &&\n typeof (error as { message: unknown }).message === 'string'\n ) {\n return error as DXLinkError\n }\n\n return { type: 'UNKNOWN', message: error instanceof Error ? error.message : String(error) }\n}\n\n/**\n * ViewModel for one RPC call — binds a protobuf service descriptor to the connection with\n * {@link createDXLinkDynamicService} and drives a single method of it.\n *\n * Construction is PURE (StrictMode-safe); the call is made in {@link start} and cancelled in\n * {@link stop}, driven by the view's `useEffect`. Unsubscribing cancels the RPC, so the\n * channel is released with the card.\n */\nexport class RpcViewModel implements ViewModel<RpcVMState> {\n readonly store = createStore<RpcVMState>(() => ({\n callState: 'active',\n responses: [],\n requests: [],\n errors: [],\n }))\n\n private readonly client: DXLinkClient\n private readonly service: DescService\n private readonly method: DescMethod\n private readonly request: Message\n\n private subscription: Subscription | null = null\n /** Request stream for bidirectional methods; null for the other models. */\n private input: ReplaySubject<Record<string, unknown>> | null = null\n private pending: RpcMessageEntry[] = []\n private flushHandle: ReturnType<typeof setTimeout> | null = null\n\n constructor(\n client: DXLinkClient,\n params: { service: DescService; method: DescMethod; request: Message }\n ) {\n this.client = client\n this.service = params.service\n this.method = params.method\n this.request = params.request\n }\n\n get isBidirectional(): boolean {\n return this.method.methodKind === 'bidi_streaming'\n }\n\n start = (): void => {\n if (this.subscription !== null) return\n\n // A start after a stop is a new call on a new channel, so it gets a new log. Without\n // this the request would appear twice on every card: React 19 StrictMode mounts,\n // unmounts and remounts the view, and the store outlives that cycle.\n this.store.setState({ callState: 'active', responses: [], requests: [], errors: [] })\n\n let responses\n try {\n const service = createDXLinkDynamicService(this.client, this.service, {\n // A descriptor chosen at runtime may declare methods the wire cannot carry; the\n // picker never offers them, and the rest of the service stays callable.\n skipUnsupportedMethods: true,\n // A debug console wants the protocol traffic in the browser log.\n logLevel: DXLinkLogLevel.DEBUG,\n })\n const call = service[this.method.localName]\n if (call === undefined) {\n throw new Error(`${this.service.typeName} does not expose ${this.method.name}`)\n }\n\n if (this.isBidirectional) {\n // `DxLinkRpcService` subscribes to the request stream only once the channel is\n // OPENED, so values emitted before that would be dropped. A ReplaySubject holds\n // them until then — and replays them if the channel re-opens after a drop.\n this.input = new ReplaySubject<Record<string, unknown>>()\n responses = call(this.input)\n this.emit(this.request)\n } else {\n responses = call(this.request as Record<string, unknown>)\n this.record('requests', formatMessage(this.method.input, this.request))\n }\n } catch (error) {\n this.fail(error)\n return\n }\n\n this.subscription = responses.subscribe({\n next: (message) => this.handleResponse(message),\n error: (error: unknown) => this.fail(error),\n complete: () => this.store.setState({ callState: 'completed' }),\n })\n }\n\n stop = (): void => {\n if (this.flushHandle !== null) {\n clearTimeout(this.flushHandle)\n this.flushHandle = null\n }\n this.pending = []\n this.input?.complete()\n this.input = null\n this.subscription?.unsubscribe()\n this.subscription = null\n }\n\n /**\n * Send another request on a bidirectional call. Rejected messages are reported as errors\n * on this channel rather than thrown, so a typo in the editor cannot take the card down.\n */\n send = (message: Message): void => {\n if (!this.isBidirectional || this.input === null) return\n this.emit(message)\n }\n\n clearErrors = (): void => {\n this.store.setState({ errors: [] })\n }\n\n close = (): void => {\n this.stop()\n }\n\n dispose = (): void => {\n this.stop()\n }\n\n private emit = (message: Message): void => {\n try {\n this.input?.next(message as Record<string, unknown>)\n this.record('requests', formatMessage(this.method.input, message))\n } catch (error) {\n this.fail(error)\n }\n }\n\n private fail = (error: unknown): void => {\n this.store.setState((state) => ({\n callState: 'failed',\n errors: prependError(state.errors, toDXLinkError(error)),\n }))\n }\n\n private handleResponse = (message: Message): void => {\n let json: JsonValue\n try {\n json = formatMessage(this.method.output, message)\n } catch (error) {\n this.fail(error)\n return\n }\n\n this.pending = [entry(json), ...this.pending]\n if (this.flushHandle === null) {\n this.flushHandle = setTimeout(this.flush, FLUSH_INTERVAL_MS)\n }\n }\n\n private flush = (): void => {\n this.flushHandle = null\n const pending = this.pending\n if (pending.length === 0) return\n this.pending = []\n this.store.setState((state) => ({\n responses: [...pending, ...state.responses].slice(0, MAX_RESPONSES),\n }))\n }\n\n private record = (key: 'requests' | 'responses', json: JsonValue): void => {\n this.store.setState((state) => ({\n [key]: [entry(json), ...state[key]].slice(0, MAX_RESPONSES),\n }))\n }\n}\n","import type {\n DescField,\n DescMessage,\n DescMethod,\n DescService,\n FileRegistry,\n JsonValue,\n} from '@bufbuild/protobuf'\nimport { ScalarType } from '@bufbuild/protobuf'\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore'\nimport UploadFileIcon from '@mui/icons-material/UploadFile'\nimport Accordion from '@mui/material/Accordion'\nimport AccordionDetails from '@mui/material/AccordionDetails'\nimport AccordionSummary from '@mui/material/AccordionSummary'\nimport Alert from '@mui/material/Alert'\nimport Box from '@mui/material/Box'\nimport Button from '@mui/material/Button'\nimport Chip from '@mui/material/Chip'\nimport FormControlLabel from '@mui/material/FormControlLabel'\nimport MenuItem from '@mui/material/MenuItem'\nimport Stack from '@mui/material/Stack'\nimport Switch from '@mui/material/Switch'\nimport TextField from '@mui/material/TextField'\nimport Typography from '@mui/material/Typography'\nimport { useMemo, useRef, useState } from 'react'\n\nimport {\n createRequestTemplate,\n fetchDescriptorSet,\n isMethodSupported,\n listServices,\n methodModel,\n parseRequest,\n readDescriptorSet,\n} from './descriptors'\nimport type { RpcRequest } from './types'\n\ninterface RpcChannelRequestProps {\n value: RpcRequest\n onChange: (value: RpcRequest) => void\n /**\n * Whether the deployment pinned the descriptor-set URL.\n *\n * Read-only rather than hidden, and Load still works: the same reasoning as the connection\n * panel's pinned endpoint — in a debug console the definitions you are calling against are\n * worth seeing even when you cannot point somewhere else.\n */\n urlLocked?: boolean\n}\n\nconst stringify = (json: JsonValue): string => JSON.stringify(json, null, 2)\n\n/** Fields the generated controls can edit; everything else is edited as JSON. */\nconst isEditableField = (field: DescField): boolean =>\n (field.fieldKind === 'scalar' || field.fieldKind === 'enum') && field.oneof === undefined\n\nconst STRING_SCALARS = new Set<ScalarType>([\n ScalarType.STRING,\n ScalarType.BYTES,\n ScalarType.INT64,\n ScalarType.UINT64,\n ScalarType.FIXED64,\n ScalarType.SFIXED64,\n ScalarType.SINT64,\n])\n\nconst scalarHelp = (scalar: ScalarType): string | undefined => {\n if (scalar === ScalarType.BYTES) return 'bytes — base64'\n if (STRING_SCALARS.has(scalar) && scalar !== ScalarType.STRING) return '64-bit — sent as a string'\n\n return undefined\n}\n\n/**\n * Controls generated from the request message descriptor.\n *\n * The protobuf-JSON text is the single source of truth: each control reads its value out of\n * the parsed object and writes a new object back. While the text is not valid JSON the\n * controls stand down — the raw editor below is then the only sane way to fix it.\n */\nconst RequestFields = ({\n message,\n json,\n onChange,\n}: {\n message: DescMessage\n json: string\n onChange: (json: string) => void\n}) => {\n const parsed = useMemo((): Record<string, JsonValue> | null => {\n try {\n const value: unknown = JSON.parse(json)\n\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, JsonValue>)\n : null\n } catch {\n return null\n }\n }, [json])\n\n const fields = message.fields.filter(isEditableField)\n if (fields.length === 0) {\n return null\n }\n\n if (parsed === null) {\n return (\n <Typography variant=\"body2\" color=\"text.secondary\">\n Fields are editable again once the request below is a JSON object.\n </Typography>\n )\n }\n\n const set = (field: DescField, fieldValue: JsonValue) =>\n onChange(stringify({ ...parsed, [field.jsonName]: fieldValue }))\n\n return (\n <Box sx={{ display: 'grid', gap: 2, gridTemplateColumns: { xs: '1fr', sm: '1fr 1fr' } }}>\n {fields.map((field) => {\n const current = parsed[field.jsonName]\n\n if (field.fieldKind === 'enum') {\n return (\n <TextField\n key={field.number}\n select\n label={field.name}\n value={typeof current === 'string' ? current : ''}\n onChange={(e) => set(field, e.target.value)}\n size=\"small\"\n helperText={field.enum.typeName}\n >\n {field.enum.values.map((enumValue) => (\n <MenuItem key={enumValue.number} value={enumValue.name}>\n {enumValue.name}\n </MenuItem>\n ))}\n </TextField>\n )\n }\n\n if (field.fieldKind !== 'scalar') {\n return null\n }\n\n if (field.scalar === ScalarType.BOOL) {\n return (\n <FormControlLabel\n key={field.number}\n control={\n <Switch\n checked={current === true}\n onChange={(e) => set(field, e.target.checked)}\n size=\"small\"\n />\n }\n label={field.name}\n />\n )\n }\n\n if (STRING_SCALARS.has(field.scalar)) {\n return (\n <TextField\n key={field.number}\n label={field.name}\n value={typeof current === 'string' ? current : ''}\n onChange={(e) => set(field, e.target.value)}\n size=\"small\"\n helperText={scalarHelp(field.scalar)}\n />\n )\n }\n\n return (\n <TextField\n key={field.number}\n label={field.name}\n type=\"number\"\n value={typeof current === 'number' ? String(current) : ''}\n onChange={(e) => set(field, e.target.value === '' ? 0 : Number(e.target.value))}\n size=\"small\"\n />\n )\n })}\n </Box>\n )\n}\n\n/**\n * RPC channel request form: load a descriptor set, pick a service and a method, fill in the\n * request.\n *\n * There is no built-in service list on purpose — the console is pointed at whatever\n * definitions the server (or a local `buf build -o set.binpb`) provides, so it is not tied\n * to any one API's release cycle.\n */\nexport const RpcChannelRequest = ({ value, onChange, urlLocked }: RpcChannelRequestProps) => {\n const [loading, setLoading] = useState(false)\n const [loadError, setLoadError] = useState<string | null>(null)\n const fileInput = useRef<HTMLInputElement>(null)\n\n const services = useMemo(\n () => (value.registry === null ? [] : listServices(value.registry)),\n [value.registry]\n )\n const service: DescService | undefined = services.find((s) => s.typeName === value.serviceName)\n const method: DescMethod | undefined = service?.method[value.methodName]\n\n const parsedRequest = useMemo(\n () => (method === undefined ? null : parseRequest(method.input, value.json)),\n [method, value.json]\n )\n\n const selectMethod = (next: DescMethod | undefined, patch: Partial<RpcRequest> = {}) =>\n onChange({\n ...value,\n ...patch,\n methodName: next?.localName ?? '',\n json: next === undefined ? '{}' : stringify(createRequestTemplate(next.input)),\n })\n\n const selectService = (next: DescService | undefined) =>\n selectMethod(next?.methods.find(isMethodSupported), { serviceName: next?.typeName ?? '' })\n\n const load = async (source: string, loader: () => Promise<void>) => {\n setLoading(true)\n setLoadError(null)\n try {\n await loader()\n } catch (error) {\n setLoadError(\n `Could not load definitions from ${source}: ${error instanceof Error ? error.message : String(error)}`\n )\n } finally {\n setLoading(false)\n }\n }\n\n // Loading a new set invalidates the current selection — preselect its first service and\n // that service's first supported method, the same as a fresh dialog would.\n const applyRegistry = (registry: FileRegistry, source: string) => {\n const firstService = listServices(registry)[0]\n const firstMethod = firstService?.methods.find(isMethodSupported)\n\n onChange({\n ...value,\n registry,\n source,\n serviceName: firstService?.typeName ?? '',\n methodName: firstMethod?.localName ?? '',\n json: firstMethod === undefined ? '{}' : stringify(createRequestTemplate(firstMethod.input)),\n })\n }\n\n const loadUrl = () =>\n load(value.url, async () => {\n applyRegistry(await fetchDescriptorSet(value.url), value.url)\n })\n\n const loadFile = (file: File) =>\n load(file.name, async () => {\n applyRegistry(await readDescriptorSet(file), file.name)\n })\n\n return (\n <Stack spacing={2.5} sx={{ pt: 1 }}>\n <Stack spacing={1.5}>\n <Typography variant=\"subtitle2\">Service definitions</Typography>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'flex-start' }}>\n <TextField\n label=\"Descriptor set URL\"\n value={value.url}\n onChange={(e) => onChange({ ...value, url: e.target.value })}\n disabled={urlLocked}\n size=\"small\"\n fullWidth\n helperText={\n urlLocked\n ? 'Fixed by this deployment.'\n : 'An endpoint serving a FileDescriptorSet, binary or protobuf-JSON.'\n }\n />\n <Button\n variant=\"outlined\"\n onClick={() => void loadUrl()}\n disabled={loading || value.url.trim() === ''}\n sx={{ mt: 0.25 }}\n >\n Load\n </Button>\n </Stack>\n <Box>\n <Button\n size=\"small\"\n startIcon={<UploadFileIcon />}\n onClick={() => fileInput.current?.click()}\n disabled={loading}\n >\n Load from file\n </Button>\n <input\n ref={fileInput}\n type=\"file\"\n hidden\n accept=\".binpb,.bin,.pb,.json\"\n onChange={(e) => {\n const file = e.target.files?.[0]\n // Clear the input so picking the same file again still fires a change.\n e.target.value = ''\n if (file !== undefined) void loadFile(file)\n }}\n />\n </Box>\n {loadError !== null && <Alert severity=\"error\">{loadError}</Alert>}\n {value.registry !== null && loadError === null && (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {services.length} service{services.length === 1 ? '' : 's'} from {value.source}\n </Typography>\n )}\n </Stack>\n\n {value.registry !== null && (\n <>\n <TextField\n select\n label=\"Service\"\n value={service?.typeName ?? ''}\n onChange={(e) => selectService(services.find((s) => s.typeName === e.target.value))}\n size=\"small\"\n fullWidth\n disabled={services.length === 0}\n helperText={services.length === 0 ? 'The descriptor set declares no services.' : ' '}\n >\n {services.map((option) => (\n <MenuItem key={option.typeName} value={option.typeName}>\n {option.typeName}\n </MenuItem>\n ))}\n </TextField>\n\n {service !== undefined && (\n <TextField\n select\n label=\"Method\"\n value={method?.localName ?? ''}\n onChange={(e) =>\n selectMethod(service.methods.find((m) => m.localName === e.target.value))\n }\n size=\"small\"\n fullWidth\n helperText={method === undefined ? ' ' : methodModel(method).description}\n >\n {service.methods.map((option) => (\n <MenuItem\n key={option.name}\n value={option.localName}\n disabled={!isMethodSupported(option)}\n >\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <span>{option.name}</span>\n <Chip size=\"small\" variant=\"outlined\" label={methodModel(option).label} />\n </Stack>\n </MenuItem>\n ))}\n </TextField>\n )}\n\n {method !== undefined && (\n <Stack spacing={1.5}>\n <Typography variant=\"subtitle2\">Request · {method.input.typeName}</Typography>\n <RequestFields\n message={method.input}\n json={value.json}\n onChange={(json) => onChange({ ...value, json })}\n />\n <Accordion\n disableGutters\n variant=\"outlined\"\n defaultExpanded\n sx={{ '&::before': { display: 'none' } }}\n >\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <Typography sx={{ fontWeight: 600 }}>Request JSON</Typography>\n </AccordionSummary>\n <AccordionDetails>\n <TextField\n value={value.json}\n onChange={(e) => onChange({ ...value, json: e.target.value })}\n multiline\n minRows={6}\n fullWidth\n size=\"small\"\n slotProps={{ input: { sx: { fontFamily: 'monospace', fontSize: 13 } } }}\n helperText=\"Canonical protobuf-JSON — exactly what is sent on the channel.\"\n />\n </AccordionDetails>\n </Accordion>\n {parsedRequest !== null && 'error' in parsedRequest && (\n <Alert severity=\"error\">{parsedRequest.error}</Alert>\n )}\n </Stack>\n )}\n </>\n )}\n </Stack>\n )\n}\n\n/** Whether the current request form can open a channel. */\nexport const canOpenRpcChannel = (value: RpcRequest): boolean => {\n if (value.registry === null) return false\n const service = value.registry.getService(value.serviceName)\n const method = service?.method[value.methodName]\n if (method === undefined || !isMethodSupported(method)) return false\n\n return !('error' in parseRequest(method.input, value.json))\n}\n"],"mappings":"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","names":["import_dxlink_console_core","import_SwapHoriz","import_dxlink_console_core","Chip","entry","Paper","Typography","Box","Stack","TextField","Alert","Button","SendIcon","SwapHorizIcon","import_protobuf","import_Alert","import_Box","import_Button","import_Chip","import_Stack","import_TextField","import_Typography","import_react","import_jsx_runtime","Typography","Box","TextField","MenuItem","FormControlLabel","Switch","Stack","Button","UploadFileIcon","Alert","Chip","Accordion","AccordionSummary","ExpandMoreIcon","AccordionDetails","import_jsx_runtime","SwapHorizIcon"]}