Skip to content

Commit a58ebd3

Browse files
committed
feat(kit)!: refactor DockClientScript context
1 parent db4e28f commit a58ebd3

File tree

9 files changed

+199
-111
lines changed

9 files changed

+199
-111
lines changed

packages/core/src/client/inject/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export async function init(): Promise<void> {
4242
const dockEl = new DockEmbedded({
4343
state,
4444
docks,
45+
rpc,
4546
})
4647
document.body.appendChild(dockEl)
4748
}

packages/core/src/client/standalone/App.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import type { DevToolsDockState } from '../webcomponents/components/DockProps'
33
import { getDevToolsRpcClient } from '@vitejs/devtools-kit/client'
44
import { useLocalStorage } from '@vueuse/core'
5-
import { computed, markRaw, ref, useTemplateRef, watchEffect } from 'vue'
5+
import { computed, markRaw, ref, shallowRef, useTemplateRef, watchEffect } from 'vue'
66
import DockEntries from '../webcomponents/components/DockEntries.vue'
77
import VitePlus from '../webcomponents/components/icons/VitePlus.vue'
88
import { IframeManager } from '../webcomponents/components/IframeManager'
@@ -14,7 +14,7 @@ const { rpc } = await getDevToolsRpcClient()
1414
// eslint-disable-next-line no-console
1515
console.log('[VITE DEVTOOLS] RPC', rpc)
1616
17-
const docks = await rpc['vite:core:list-dock-entries']()
17+
const docks = shallowRef(await rpc['vite:core:list-dock-entries']())
1818
// eslint-disable-next-line no-console
1919
console.log('[VITE DEVTOOLS] Docks', docks)
2020
@@ -40,9 +40,9 @@ watchEffect(() => {
4040
}, { flush: 'sync' })
4141
4242
const isDragging = ref(false)
43-
const entry = computed(() => state.value.dockEntry || docks[0])
43+
const entry = computed(() => state.value.dockEntry || docks.value[0])
4444
45-
const { selectDockEntry } = useStateHandlers(state)
45+
const { selectDockEntry } = useStateHandlers(state, docks, rpc, 'standalone')
4646
</script>
4747

4848
<template>

packages/core/src/client/webcomponents/components/Dock.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ const panelStyle = computed(() => {
217217
return style
218218
})
219219
220-
const { selectDockEntry } = useStateHandlers(state)
220+
const { selectDockEntry } = useStateHandlers(state, docks, props.rpc, 'embedded')
221221
222222
onMounted(() => {
223223
bringUp()

packages/core/src/client/webcomponents/components/DockEmbedded.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
22
import type { DevToolsDockEntry } from '@vitejs/devtools-kit'
3+
import type { DevToolsRpcClient } from '@vitejs/devtools-kit/client'
34
import type { DevToolsDockState } from './DockProps'
45
import Dock from './Dock.vue'
56
import DockPanel from './DockPanel.vue'
@@ -8,13 +9,15 @@ import FloatingTooltip from './FloatingTooltip.vue'
89
defineProps<{
910
state: DevToolsDockState
1011
docks: DevToolsDockEntry[]
12+
rpc: DevToolsRpcClient
1113
}>()
1214
</script>
1315

1416
<template>
1517
<Dock
1618
:state="state"
1719
:docks="docks"
20+
:rpc="rpc"
1821
>
1922
<template #default="{ dockEl, entry, panelMargins, isDragging }">
2023
<DockPanel

packages/core/src/client/webcomponents/components/DockProps.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { DevToolsDockEntry } from '@vitejs/devtools-kit'
2+
import type { DevToolsRpcClient } from '@vitejs/devtools-kit/client'
23

34
export interface DevToolsDockState {
45
width: number
@@ -14,4 +15,5 @@ export interface DevToolsDockState {
1415
export interface DockProps {
1516
state: DevToolsDockState
1617
docks: DevToolsDockEntry[]
18+
rpc: DevToolsRpcClient
1719
}

packages/core/src/client/webcomponents/state/state.ts

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,36 @@
11
import type { DevToolsDockEntry } from '@vitejs/devtools-kit'
2-
import type { DockClientScriptContext } from '@vitejs/devtools-kit/client'
2+
import type { DevToolsRpcClient, DockClientScriptClientType, DockClientScriptContext, DockClientScriptCurrent, DockClientScriptDocks } from '@vitejs/devtools-kit/client'
33
import type { Ref } from 'vue'
44
import type { DevToolsDockState } from '../components/DockProps'
55
import { computed, reactive } from 'vue'
66

7-
export function useStateHandlers(state: Ref<DevToolsDockState>) {
7+
export function useStateHandlers(
8+
state: Ref<DevToolsDockState>,
9+
dockEntries: Ref<DevToolsDockEntry[]>,
10+
rpc: DevToolsRpcClient,
11+
clientType: DockClientScriptClientType,
12+
) {
13+
const docks: DockClientScriptDocks = reactive({
14+
switchEntry: async (id: string | null) => {
15+
if (id === null) {
16+
selectDockEntry(undefined)
17+
return true
18+
}
19+
const entry = dockEntries.value.find((d: DevToolsDockEntry) => d.id === id)
20+
if (!entry) {
21+
return false
22+
}
23+
selectDockEntry(entry)
24+
return true
25+
},
26+
minimize: async () => {
27+
state.value.open = false
28+
},
29+
reveal: async () => {
30+
state.value.open = true
31+
},
32+
})
33+
834
function importScript(entry: DevToolsDockEntry): Promise<(context: DockClientScriptContext) => void | Promise<void>> {
935
const id = `${entry.type}:${entry.id}`
1036
return import(/* @vite-ignore */ ['/.devtools', 'imports'].join('-'))
@@ -31,10 +57,9 @@ export function useStateHandlers(state: Ref<DevToolsDockState>) {
3157
return
3258
}
3359

34-
const scriptContext: DockClientScriptContext = reactive({
35-
dockEntry: entry,
36-
// @ts-expect-error cast for unwraping
37-
dockState: computed<'active' | 'inactive'>({
60+
const current: DockClientScriptCurrent = reactive({
61+
entryMeta: entry,
62+
state: computed<'active' | 'inactive'>({
3863
get() {
3964
return state.value.dockEntry?.id === entry.id ? 'active' : 'inactive'
4065
},
@@ -45,9 +70,13 @@ export function useStateHandlers(state: Ref<DevToolsDockState>) {
4570
state.value.dockEntry = undefined
4671
},
4772
}),
48-
hidePanel() {
49-
state.value.open = false
50-
},
73+
})
74+
75+
const scriptContext: DockClientScriptContext = reactive({
76+
rpc,
77+
docks,
78+
current,
79+
clientType,
5180
})
5281

5382
// If it's an action, run and return (early exit)
@@ -63,6 +92,7 @@ export function useStateHandlers(state: Ref<DevToolsDockState>) {
6392
}
6493

6594
return {
95+
docks,
6696
selectDockEntry,
6797
}
6898
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import type { BirpcReturn, DevToolsDockEntry, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions } from '../types'
2+
3+
export type DockClientScriptClientType = 'embedded' | 'standalone'
4+
5+
/**
6+
* Context for client scripts running in dock entries
7+
*/
8+
export interface DockClientScriptContext {
9+
/**
10+
* Interactions with the docks
11+
*/
12+
docks: DockClientScriptDocks
13+
14+
/**
15+
* The state if the current dock entry
16+
*/
17+
current: DockClientScriptCurrent
18+
19+
/**
20+
* The RPC client to interact with the server
21+
*/
22+
rpc: BirpcReturn<DevToolsRpcServerFunctions, DevToolsRpcClientFunctions>
23+
24+
/**
25+
* Type of the client environment
26+
*
27+
* 'embedded' - running inside an embedded floating panel
28+
* 'standalone' - running inside a standlone window (no user app)
29+
*/
30+
clientType: DockClientScriptClientType
31+
}
32+
33+
export interface DockClientScriptDocks {
34+
/**
35+
* Switch to the selected dock entry, pass `null` to clear the selection
36+
*
37+
* @returns Whether the selection was changed successfully
38+
*/
39+
switchEntry: (id: string | null) => Promise<boolean>
40+
41+
/**
42+
* Minimize the panel
43+
*/
44+
minimize: () => Promise<void>
45+
46+
/**
47+
* Reveal the panel
48+
*/
49+
reveal: () => Promise<void>
50+
}
51+
52+
export interface DockClientScriptCurrent {
53+
/**
54+
* The dock entry info of the current dock item
55+
*/
56+
entryMeta: DevToolsDockEntry
57+
58+
/**
59+
* The current state of the dock
60+
*/
61+
state: 'active' | 'inactive'
62+
63+
/**
64+
* The panel element to mount into, when the entry type is `custom-render`
65+
*/
66+
elPanel?: HTMLDivElement | null
67+
68+
/**
69+
* The iframe element to mount into, when the entry type is `iframe`
70+
*/
71+
elIframe?: HTMLIFrameElement | null
72+
73+
/**
74+
* The dock icon element
75+
*/
76+
elDockIcon?: HTMLDivElement | null
77+
}

packages/kit/src/client/index.ts

Lines changed: 2 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,2 @@
1-
import type { WebSocketRpcClientOptions } from '@vitejs/devtools-rpc/presets/ws/client'
2-
import type { BirpcOptions, BirpcReturn } from 'birpc'
3-
import type { ConnectionMeta, DevToolsDockEntry, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions } from '../types'
4-
import { createRpcClient } from '@vitejs/devtools-rpc'
5-
import { createWsRpcPreset } from '@vitejs/devtools-rpc/presets/ws/client'
6-
7-
function isNumeric(str: string | number | undefined) {
8-
if (str == null)
9-
return false
10-
return `${+str}` === `${str}`
11-
}
12-
13-
export interface DevToolsRpcClientOptions {
14-
connectionMeta?: ConnectionMeta
15-
baseURL?: string[]
16-
wsOptions?: Partial<WebSocketRpcClientOptions>
17-
rpcOptions?: Partial<BirpcOptions<DevToolsRpcServerFunctions>>
18-
}
19-
20-
/**
21-
* Context for client scripts running in dock entries
22-
*/
23-
export interface DockClientScriptContext {
24-
/**
25-
* The dock entry info of the current dock item
26-
*/
27-
dockEntry: DevToolsDockEntry
28-
/**
29-
* The current state of the dock
30-
*/
31-
dockState: 'active' | 'inactive'
32-
/**
33-
* Type of the client environment
34-
*
35-
* 'embedded' - running inside an embedded floating panel
36-
* 'standalone' - running inside a standlone window (no user app)
37-
*/
38-
clientType: 'embedded' | 'standalone'
39-
/**
40-
* Function to hide the panel, if applicable
41-
*/
42-
hidePanel: () => void
43-
/**
44-
* The panel element to mount into, if applicable
45-
*/
46-
elPanel?: HTMLElement | null
47-
}
48-
49-
export async function getDevToolsRpcClient(
50-
options: DevToolsRpcClientOptions = {},
51-
): Promise<{
52-
connectionMeta: ConnectionMeta
53-
rpc: BirpcReturn<DevToolsRpcServerFunctions, DevToolsRpcClientFunctions>
54-
}> {
55-
const {
56-
baseURL = '/.devtools/',
57-
rpcOptions = {},
58-
} = options
59-
const urls = Array.isArray(baseURL) ? baseURL : [baseURL]
60-
let connectionMeta: ConnectionMeta | undefined = options.connectionMeta
61-
62-
if (!connectionMeta) {
63-
const errors: Error[] = []
64-
for (const url of urls) {
65-
try {
66-
connectionMeta = await fetch(`${url}.vdt-connection.json`)
67-
.then(r => r.json()) as ConnectionMeta
68-
break
69-
}
70-
catch (e) {
71-
errors.push(e as Error)
72-
}
73-
}
74-
if (!connectionMeta) {
75-
throw new Error(`Failed to get connection meta from ${urls.join(', ')}`, {
76-
cause: errors,
77-
})
78-
}
79-
}
80-
81-
const url = isNumeric(connectionMeta.websocket)
82-
? `${location.protocol.replace('http', 'ws')}//${location.hostname}:${connectionMeta.websocket}`
83-
: connectionMeta.websocket as string
84-
85-
const rpc = createRpcClient<DevToolsRpcServerFunctions, DevToolsRpcClientFunctions>({}, {
86-
preset: createWsRpcPreset({
87-
url,
88-
...options.wsOptions,
89-
}),
90-
rpcOptions,
91-
})
92-
93-
return {
94-
connectionMeta,
95-
rpc,
96-
}
97-
}
1+
export * from './client-script'
2+
export * from './rpc'

0 commit comments

Comments
 (0)