From 347230494675312a4121be633b80a24ac720117d Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Sun, 5 Apr 2026 23:26:20 +0200 Subject: [PATCH 1/3] fix(devtools): let birpc be singlesource of turth for server<->client comms --- .../devtools/client/composables/client.ts | 25 +++++++++++++++--- packages/devtools/client/composables/rpc.ts | 26 ++----------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/packages/devtools/client/composables/client.ts b/packages/devtools/client/composables/client.ts index 6031ed9a10..2546a0f404 100644 --- a/packages/devtools/client/composables/client.ts +++ b/packages/devtools/client/composables/client.ts @@ -1,13 +1,14 @@ import type { useRoute, useRouter } from '#imports' import type { NuxtDevtoolsClient, NuxtDevtoolsHostClient, NuxtDevtoolsIframeClient } from '@nuxt/devtools-kit/types' import type { Unhead } from '@unhead/schema' +import type { DevToolsRpcClient } from '@vitejs/devtools-kit/client' import type { ComputedRef } from 'vue' import { useState } from '#imports' import { useColorMode } from '@vueuse/core' import { computed, ref } from 'vue' import { renderMarkdown } from './client-services/markdown' import { renderCodeHighlight } from './client-services/shiki' -import { extendedRpcMap, rpc } from './rpc' +import { connectPromise, rpc, rpcClient } from './rpc' export function useClient() { return useState('devtools-client') @@ -59,13 +60,31 @@ export function useInjectionClient(): ComputedRef { return renderMarkdown(code) }, extendClientRpc(namespace, functions) { - extendedRpcMap.set(namespace, functions) + const register = (client: DevToolsRpcClient) => { + for (const [name, handler] of Object.entries(functions)) { + if (typeof handler === 'function') { + client.client.register({ + name: `${namespace}:${name}`, + type: 'event', + handler: handler as any, + }) + } + } + } + + if (rpcClient) + register(rpcClient) + else + connectPromise.then(register) return new Proxy({}, { get(_, key) { if (typeof key !== 'string') return - return (rpc as any)[`${namespace}:${key}`] + return async (...args: any[]) => { + const client = rpcClient || await connectPromise + return client.call(`${namespace}:${key}` as any, ...args as any) + } }, }) }, diff --git a/packages/devtools/client/composables/rpc.ts b/packages/devtools/client/composables/rpc.ts index 007e2dc73d..f89236ad97 100644 --- a/packages/devtools/client/composables/rpc.ts +++ b/packages/devtools/client/composables/rpc.ts @@ -12,11 +12,9 @@ export const clientFunctions = { // will be added in setup/client-rpc.ts } as ClientFunctions -export const extendedRpcMap = new Map() +export let rpcClient: DevToolsRpcClient | undefined -let rpcClient: DevToolsRpcClient | undefined - -const connectPromise = connectDevToolsRpc() +export const connectPromise = connectDevToolsRpc() /** * Proxy-based RPC object that provides backward-compatible `rpc.functionName()` interface. @@ -26,13 +24,6 @@ export const rpc = new Proxy({} as AsyncServerFunctions, { get: (_, method: string) => { return async (...args: any[]) => { const client = rpcClient || await connectPromise - // Check extended RPC map first for namespaced functions - if (method.includes(':')) { - const [namespace, fnName] = method.split(':') as [string, string] - const extFn = extendedRpcMap.get(namespace)?.[fnName] - if (extFn) - return extFn(...args) - } return client.call(method as any, ...args as any) } }, @@ -55,19 +46,6 @@ async function connectDevToolsRpc(): Promise { } } - // Register extended client RPC functions - for (const [namespace, fns] of extendedRpcMap) { - for (const [fnName, handler] of Object.entries(fns)) { - if (typeof handler === 'function') { - client.client.register({ - name: `${namespace}:${fnName}`, - type: 'event', - handler: handler as any, - }) - } - } - } - // eslint-disable-next-line no-console console.log('[nuxt-devtools] Connected to Vite DevTools RPC') wsConnecting.value = false From 9bfd78e6a5f579a9e1d42193ed149e1507670ef4 Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Mon, 6 Apr 2026 00:07:31 +0200 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- packages/devtools/client/composables/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools/client/composables/client.ts b/packages/devtools/client/composables/client.ts index 2546a0f404..baad9b804a 100644 --- a/packages/devtools/client/composables/client.ts +++ b/packages/devtools/client/composables/client.ts @@ -75,7 +75,7 @@ export function useInjectionClient(): ComputedRef { if (rpcClient) register(rpcClient) else - connectPromise.then(register) + void connectPromise.then(register, () => {}) return new Proxy({}, { get(_, key) { From 1f87b76cbec61b21f22a6e35c25c905c93f0a603 Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Mon, 6 Apr 2026 14:21:05 +0200 Subject: [PATCH 3/3] fix(devtools): let birpc be singlesource of turth for server<->client comms --- packages/devtools/client/composables/client.ts | 6 +++--- packages/devtools/client/composables/rpc.ts | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/devtools/client/composables/client.ts b/packages/devtools/client/composables/client.ts index baad9b804a..46fa973720 100644 --- a/packages/devtools/client/composables/client.ts +++ b/packages/devtools/client/composables/client.ts @@ -72,8 +72,8 @@ export function useInjectionClient(): ComputedRef { } } - if (rpcClient) - register(rpcClient) + if (rpcClient.value) + register(rpcClient.value) else void connectPromise.then(register, () => {}) @@ -82,7 +82,7 @@ export function useInjectionClient(): ComputedRef { if (typeof key !== 'string') return return async (...args: any[]) => { - const client = rpcClient || await connectPromise + const client = rpcClient.value || await connectPromise return client.call(`${namespace}:${key}` as any, ...args as any) } }, diff --git a/packages/devtools/client/composables/rpc.ts b/packages/devtools/client/composables/rpc.ts index f89236ad97..5c05def57d 100644 --- a/packages/devtools/client/composables/rpc.ts +++ b/packages/devtools/client/composables/rpc.ts @@ -12,7 +12,7 @@ export const clientFunctions = { // will be added in setup/client-rpc.ts } as ClientFunctions -export let rpcClient: DevToolsRpcClient | undefined +export const rpcClient = shallowRef() export const connectPromise = connectDevToolsRpc() @@ -23,7 +23,7 @@ export const connectPromise = connectDevToolsRpc() export const rpc = new Proxy({} as AsyncServerFunctions, { get: (_, method: string) => { return async (...args: any[]) => { - const client = rpcClient || await connectPromise + const client = rpcClient.value || await connectPromise return client.call(method as any, ...args as any) } }, @@ -33,7 +33,7 @@ async function connectDevToolsRpc(): Promise { try { const client = await getDevToolsRpcClient() - rpcClient = client + rpcClient.value = client // Register client functions so the server can call them for (const [name, handler] of Object.entries(clientFunctions)) { @@ -65,7 +65,7 @@ async function connectDevToolsRpc(): Promise { * Used by setup/client-rpc.ts to register functions that are set up later. */ export async function registerClientFunctions() { - const client = rpcClient || await connectPromise + const client = rpcClient.value || await connectPromise for (const [name, handler] of Object.entries(clientFunctions)) { if (typeof handler === 'function') { try {