Skip to content

Commit 5b148a6

Browse files
authored
chore: migrate RPC to Vite DevTools Kit's RPC layer (#957)
1 parent ce21c44 commit 5b148a6

13 files changed

Lines changed: 281 additions & 407 deletions

File tree

packages/devtools-kit/src/_types/client-api.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import type {} from '@nuxt/schema'
2-
import type { BirpcReturn } from 'birpc'
32
import type { Hookable } from 'hookable'
43
import type { NuxtApp } from 'nuxt/app'
54
import type { AppConfig } from 'nuxt/schema'
65
import type { $Fetch } from 'ofetch'
76
import type { BuiltinLanguage } from 'shiki'
87
import type { Ref } from 'vue'
98
import type { HookInfo, LoadingTimeMetric, PluginMetric } from './integrations'
10-
import type { ClientFunctions, ServerFunctions } from './rpc'
9+
import type { ServerFunctions } from './rpc'
1110
import type { TimelineMetrics } from './timeline-metrics'
1211

1312
export interface DevToolsFrameState {
@@ -106,16 +105,20 @@ export interface CodeHighlightOptions {
106105
grammarContextCode?: string
107106
}
108107

108+
export type AsyncServerFunctions = {
109+
[K in keyof ServerFunctions]: (...args: Parameters<ServerFunctions[K]>) => Promise<Awaited<ReturnType<ServerFunctions[K]>>>
110+
}
111+
109112
export interface NuxtDevtoolsClient {
110-
rpc: BirpcReturn<ServerFunctions, ClientFunctions>
113+
rpc: AsyncServerFunctions
111114
renderCodeHighlight: (code: string, lang?: BuiltinLanguage, options?: CodeHighlightOptions) => {
112115
code: string
113116
supported: boolean
114117
}
115118
renderMarkdown: (markdown: string) => string
116119
colorMode: string
117120

118-
extendClientRpc: <ServerFunctions extends object = Record<string, unknown>, ClientFunctions extends object = Record<string, unknown>>(name: string, functions: ClientFunctions) => BirpcReturn<ServerFunctions, ClientFunctions>
121+
extendClientRpc: <ServerFunctions extends object = Record<string, unknown>, ClientFunctions extends object = Record<string, unknown>>(name: string, functions: ClientFunctions) => ServerFunctions
119122
}
120123

121124
export interface NuxtDevtoolsIframeClient {

packages/devtools-kit/src/_types/options.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,7 @@ export interface ModuleOptions {
4444
viteInspect?: boolean
4545

4646
/**
47-
* Disable dev time authorization check.
48-
*
49-
* **NOT RECOMMENDED**, only use this if you know what you are doing.
50-
*
51-
* @see https://github.com/nuxt/devtools/pull/257
52-
* @default false
47+
* @deprecated Auth is now handled by Vite DevTools. This option is ignored.
5348
*/
5449
disableAuthorization?: boolean
5550

packages/devtools-kit/src/_types/server-ctx.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,33 @@ import type { Nuxt, NuxtDebugModuleMutationRecord } from 'nuxt/schema'
33
import type { ModuleOptions } from './options'
44
import type { ClientFunctions, ServerFunctions } from './rpc'
55

6+
/**
7+
* Compatibility RPC interface that supports broadcast and function access.
8+
* Backed by Vite DevTools Kit's RpcFunctionsHost internally.
9+
*/
10+
export interface NuxtDevtoolsRpc {
11+
/**
12+
* Broadcast proxy for calling client functions.
13+
* Supports `rpc.broadcast.refresh.asEvent(event)` pattern for backward compatibility.
14+
*/
15+
broadcast: {
16+
[K in keyof ClientFunctions]: ClientFunctions[K] & { asEvent: ClientFunctions[K] }
17+
}
18+
19+
/**
20+
* Proxy for accessing server functions locally.
21+
*/
22+
functions: ServerFunctions
23+
}
24+
625
/**
726
* @internal
827
*/
928
export interface NuxtDevtoolsServerContext {
1029
nuxt: Nuxt
1130
options: ModuleOptions
1231

13-
rpc: BirpcGroup<ClientFunctions, ServerFunctions>
32+
rpc: NuxtDevtoolsRpc
1433

1534
/**
1635
* Hook to open file in editor
@@ -23,7 +42,7 @@ export interface NuxtDevtoolsServerContext {
2342
refresh: (event: keyof ServerFunctions) => void
2443

2544
/**
26-
* Ensure dev auth token is valid, throw if not
45+
* @deprecated Auth is now handled by Vite DevTools. This is a noop.
2746
*/
2847
ensureDevAuthToken: (token: string) => Promise<void>
2948

packages/devtools-kit/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ export function startSubprocess(
132132
}
133133
}
134134

135+
/**
136+
* Extend server RPC with namespaced functions.
137+
*
138+
* Returns an object with a `broadcast` proxy for calling client functions.
139+
*/
135140
export function extendServerRpc<ClientFunctions extends object = Record<string, unknown>, ServerFunctions extends object = Record<string, unknown>>(
136141
namespace: string,
137142
functions: ServerFunctions,
Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,3 @@
1-
<script setup lang="ts">
2-
import { AuthConfirm } from '~/composables/dialog'
3-
</script>
4-
51
<template>
6-
<AuthConfirm v-slot="{ resolve }">
7-
<NDialog :model-value="!isDevAuthed" class="border-none" @close="resolve(false)">
8-
<AuthRequiredPanel>
9-
<template #actions>
10-
<NButton @click="resolve(false)">
11-
Cancel
12-
</NButton>
13-
</template>
14-
</AuthRequiredPanel>
15-
</NDialog>
16-
</AuthConfirm>
2+
<div />
173
</template>
Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,4 @@
1-
<script setup lang="ts">
2-
import { onMounted, ref } from 'vue'
3-
import { devAuthToken, isDevAuthed, requestForAuth, updateDevAuthToken } from '~/composables/dev-auth'
4-
import { rpc } from '~/composables/rpc'
5-
6-
onMounted(async () => {
7-
if (!isDevAuthed.value) {
8-
if (devAuthToken.value) {
9-
const result = await rpc.verifyAuthToken(devAuthToken.value)
10-
if (result)
11-
isDevAuthed.value = true
12-
}
13-
}
14-
if (!isDevAuthed.value)
15-
requestForAuth()
16-
})
17-
18-
const authInput = ref('')
19-
const isFailed = ref(false)
20-
21-
async function input() {
22-
const token = authInput.value.trim()
23-
isFailed.value = false
24-
await rpc.verifyAuthToken(token)
25-
.then((result) => {
26-
if (result) {
27-
isDevAuthed.value = true
28-
updateDevAuthToken(token)
29-
}
30-
else {
31-
isFailed.value = true
32-
}
33-
})
34-
}
35-
</script>
36-
371
<template>
38-
<NPanelGrids v-if="!isDevAuthed">
39-
<NCard flex="~ col gap-2" mxa p6>
40-
<h3 class="mb2 text-lg font-medium leading-6" flex="~ items-center gap-1" text-orange>
41-
<span class="i-carbon-information-square" /> Permissions required
42-
</h3>
43-
<p>
44-
This operation requires permissions for running command and access files from the browser.
45-
</p>
46-
<p>
47-
A request is sent to the server.<br>
48-
Please check your terminal for the instructions and then come back.
49-
</p>
50-
<div flex="~ gap-3" mt5 justify-between>
51-
<form relative flex="~ col gap-2" @submit.prevent="input">
52-
<p text-xs op-50>
53-
Or you can manually paste the token below:
54-
</p>
55-
<div flex="~ inline gap-2 items-center">
56-
<NTextInput
57-
v-model="authInput" placeholder="Enter token here"
58-
:n="isFailed ? 'red' : undefined"
59-
@keydown.enter="input"
60-
/>
61-
<NButton n="green" h-full icon="i-carbon-arrow-right" @click="input" />
62-
</div>
63-
</form>
64-
<div flex="~ gap-2 items-end">
65-
<slot name="actions" />
66-
<NButton disabled icon="i-carbon-time">
67-
Waiting for authorization...
68-
</NButton>
69-
</div>
70-
</div>
71-
</NCard>
72-
</NPanelGrids>
73-
<template v-else>
74-
<slot />
75-
</template>
2+
<!-- Auth is now handled by Vite DevTools -->
3+
<slot />
764
</template>
Lines changed: 12 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,26 @@
1-
import { devtoolsUiShowNotification } from '#imports'
2-
import { until } from '@vueuse/core'
31
import { parseUA } from 'ua-parser-modern'
42
import { ref } from 'vue'
5-
import { AuthConfirm } from './dialog'
6-
import { rpc } from './rpc'
73

8-
export const devAuthToken = ref<string | null>(localStorage.getItem('__nuxt_dev_token__'))
4+
/** @deprecated Auth is now handled by Vite DevTools */
5+
export const devAuthToken = ref<string | null>('disabled')
96

10-
export const isDevAuthed = ref(false)
7+
/** @deprecated Auth is now handled by Vite DevTools */
8+
export const isDevAuthed = ref(true)
119

12-
const bc = new BroadcastChannel('__nuxt_dev_token__')
13-
14-
bc.addEventListener('message', (e) => {
15-
if (e.data.event === 'new-token') {
16-
if (e.data.data === devAuthToken.value)
17-
return
18-
const token = e.data.data
19-
rpc.verifyAuthToken(token)
20-
.then((result) => {
21-
devAuthToken.value = result ? token : null
22-
isDevAuthed.value = result
23-
})
24-
}
25-
})
26-
27-
export function updateDevAuthToken(token: string) {
28-
devAuthToken.value = token
29-
isDevAuthed.value = true
30-
localStorage.setItem('__nuxt_dev_token__', token)
31-
bc.postMessage({ event: 'new-token', data: token })
10+
/** @deprecated Auth is now handled by Vite DevTools */
11+
export function updateDevAuthToken(_token: string) {
12+
console.warn('[nuxt-devtools] `updateDevAuthToken` is deprecated. Auth is now handled by Vite DevTools.')
3213
}
3314

15+
/** @deprecated Auth is now handled by Vite DevTools */
3416
export async function ensureDevAuthToken() {
35-
if (isDevAuthed.value)
36-
return devAuthToken.value!
37-
38-
if (!devAuthToken.value)
39-
await authConfirmAction()
40-
41-
isDevAuthed.value = await rpc.verifyAuthToken(devAuthToken.value!)
42-
if (!isDevAuthed.value) {
43-
devAuthToken.value = null
44-
devtoolsUiShowNotification({
45-
message: 'Invalid auth token, action canceled',
46-
icon: 'i-carbon-warning-alt',
47-
classes: 'text-red',
48-
})
49-
await authConfirmAction()
50-
throw new Error('[Nuxt DevTools] Invalid auth token')
51-
}
52-
53-
return devAuthToken.value!
17+
console.warn('[nuxt-devtools] `ensureDevAuthToken` is deprecated. Auth is now handled by Vite DevTools.')
18+
return ''
5419
}
5520

5621
export const userAgentInfo = parseUA(navigator.userAgent)
5722

23+
/** @deprecated Auth is now handled by Vite DevTools */
5824
export async function requestForAuth() {
59-
const desc = [
60-
userAgentInfo.browser.name,
61-
userAgentInfo.browser.version,
62-
'|',
63-
userAgentInfo.os.name,
64-
userAgentInfo.os.version,
65-
userAgentInfo.device.type,
66-
].filter(i => i).join(' ')
67-
return await rpc.requestForAuth(desc, window.location.origin)
68-
}
69-
70-
async function authConfirmAction() {
71-
if (!devAuthToken.value)
72-
requestForAuth()
73-
74-
const result = await Promise.race([
75-
AuthConfirm.start(),
76-
until(devAuthToken.value).toBeTruthy(),
77-
])
78-
79-
if (result === false) {
80-
// @unocss-include
81-
devtoolsUiShowNotification({
82-
message: 'Action canceled',
83-
icon: 'carbon-close',
84-
classes: 'text-orange',
85-
})
86-
throw new Error('[Nuxt DevTools] User canceled auth')
87-
}
25+
console.warn('[nuxt-devtools] `requestForAuth` is deprecated. Auth is now handled by Vite DevTools.')
8826
}

0 commit comments

Comments
 (0)