Skip to content

Commit 6989218

Browse files
committed
feat(core): use shared state for docks entries
1 parent c6df7aa commit 6989218

File tree

12 files changed

+76
-121
lines changed

12 files changed

+76
-121
lines changed

docs/kit/index.md

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -396,30 +396,6 @@ export default function myPlugin(): Plugin {
396396

397397
The `broadcast` method returns a promise that resolves to an array of results from all clients (some may be `undefined` if the client doesn't implement the function).
398398

399-
**Example: Broadcasting dock updates**
400-
401-
Here's a real-world example of how the built-in docks system broadcasts updates:
402-
403-
```ts
404-
// When a dock entry is updated, broadcast to all clients
405-
docksHost.events.on('dock:entry:updated', () => {
406-
rpcHost.broadcast('vite:internal:docks:updated')
407-
})
408-
```
409-
410-
And on the client side:
411-
412-
```ts
413-
rpc.client.register({
414-
name: 'vite:internal:docks:updated' satisfies keyof DevToolsRpcClientFunctions,
415-
type: 'action',
416-
handler: async () => {
417-
// Refresh the dock entries list
418-
await updateDocksEntries()
419-
},
420-
})
421-
```
422-
423399
### Shared State
424400

425401
The DevTools Kit provides a built-in shared state system that enables you to share data between the server and client with automatic synchronization.

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

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import type { DevToolsDockEntry, DevToolsRpcClientFunctions } from '@vitejs/devtools-kit'
1+
import type { DevToolsDockEntry } from '@vitejs/devtools-kit'
22
import type { DevToolsRpcClient, DockEntryState, DockEntryStateEvents, DockPanelStorage } from '@vitejs/devtools-kit/client'
3+
import type { SharedState } from '@vitejs/devtools-kit/utils/shared-state'
34
import type { Ref, ShallowRef } from 'vue'
45
import { createEventEmitter } from '@vitejs/devtools-kit/utils/events'
56
import { markRaw, reactive, shallowRef, watch } from 'vue'
@@ -64,31 +65,20 @@ export function createDockEntryState(
6465
return state
6566
}
6667

68+
function sharedStateToRef<T>(sharedState: SharedState<T>): ShallowRef<T> {
69+
const ref = shallowRef<T>(sharedState.value() as T)
70+
sharedState.on('updated', (newState: T) => {
71+
ref.value = newState
72+
})
73+
return ref
74+
}
75+
6776
let _docksEntriesRef: ShallowRef<DevToolsDockEntry[]> | undefined
6877
export async function useDocksEntries(rpc: DevToolsRpcClient): Promise<Ref<DevToolsDockEntry[]>> {
6978
if (_docksEntriesRef) {
7079
return _docksEntriesRef
7180
}
72-
const dockEntries = _docksEntriesRef = shallowRef<DevToolsDockEntry[]>([])
73-
async function updateDocksEntries() {
74-
if (!rpc.isTrusted) {
75-
console.warn('[VITE DEVTOOLS] Untrusted client, skipping docks entries update')
76-
return
77-
}
78-
dockEntries.value = (await rpc.call('vite:internal:docks:list'))
79-
.map(entry => Object.freeze(entry))
80-
// eslint-disable-next-line no-console
81-
console.log('[VITE DEVTOOLS] Docks Entries Updated', [...dockEntries.value])
82-
}
83-
rpc.events.on('rpc:is-trusted:updated', (isTrusted) => {
84-
if (isTrusted)
85-
updateDocksEntries()
86-
})
87-
rpc.client.register({
88-
name: 'vite:internal:docks:updated' satisfies keyof DevToolsRpcClientFunctions,
89-
type: 'action',
90-
handler: () => updateDocksEntries(),
91-
})
92-
await updateDocksEntries()
93-
return dockEntries
81+
const state = await rpc.sharedState.get('vite:internal:docks', { initialValue: [] })
82+
_docksEntriesRef = sharedStateToRef(state)
83+
return _docksEntriesRef
9484
}

packages/core/src/node/context.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,19 @@ export async function createDevToolsContext(
4444
rpcHost.register(fn)
4545
}
4646

47+
const docksSharedState = await rpcHost.sharedState.get('vite:internal:docks', { initialValue: [] })
48+
4749
// Register hosts side effects
4850
docksHost.events.on('dock:entry:updated', debounce(() => {
49-
rpcHost.broadcast({
50-
method: 'vite:internal:docks:updated',
51-
args: [],
52-
})
51+
docksSharedState.mutate(() => context.docks.values())
5352
}, 10))
53+
5454
terminalsHost.events.on('terminal:session:updated', debounce(() => {
5555
rpcHost.broadcast({
5656
method: 'vite:internal:terminals:updated',
5757
args: [],
5858
})
59-
// New terminals might affect the visibility of the terminals dock entry, we trigger it here as well
60-
rpcHost.broadcast({
61-
method: 'vite:internal:docks:updated',
62-
args: [],
63-
})
59+
docksSharedState.mutate(() => context.docks.values())
6460
}, 10))
6561
terminalsHost.events.on('terminal:session:stream-chunk', (data) => {
6662
rpcHost.broadcast({

packages/core/src/node/host-docks.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { DevToolsDockHost as DevToolsDockHostType, DevToolsDockUserEntry, DevToolsNodeContext } from '@vitejs/devtools-kit'
1+
import type { DevToolsDockEntry, DevToolsDockHost as DevToolsDockHostType, DevToolsDockUserEntry, DevToolsNodeContext, DevToolsViewBuiltin } from '@vitejs/devtools-kit'
22
import { createEventEmitter } from '@vitejs/devtools-kit/utils/events'
33

44
export class DevToolsDockHost implements DevToolsDockHostType {
@@ -10,8 +10,24 @@ export class DevToolsDockHost implements DevToolsDockHostType {
1010
) {
1111
}
1212

13-
values(): DevToolsDockUserEntry[] {
14-
return Array.from(this.views.values())
13+
values(): DevToolsDockEntry[] {
14+
const context = this.context
15+
const builtinDocksEntries: DevToolsViewBuiltin[] = [
16+
{
17+
type: '~builtin',
18+
id: '~terminals',
19+
title: 'Terminals',
20+
icon: 'ph:terminal-duotone',
21+
get isHidden() {
22+
return context.terminals.sessions.size === 0
23+
},
24+
},
25+
]
26+
27+
return [
28+
...Array.from(this.views.values()),
29+
...builtinDocksEntries,
30+
]
1531
}
1632

1733
register<T extends DevToolsDockUserEntry>(view: T, force?: boolean): {

packages/core/src/node/rpc-shared-state.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function createRpcSharedStateServerHost(
5151
}
5252
debug('new-state', key)
5353
const state = createSharedState<T>({
54-
initialState: options.initialValue,
54+
initialValue: options.initialValue,
5555
enablePatches: false,
5656
})
5757
registerSharedState(key, state)

packages/core/src/node/rpc/index.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import type { DevToolsTerminalSessionStreamChunkEvent, RpcDefinitionsFilter, RpcDefinitionsToFunctions } from '@vitejs/devtools-kit'
1+
import type { DevToolsDockEntry, DevToolsTerminalSessionStreamChunkEvent, RpcDefinitionsFilter, RpcDefinitionsToFunctions } from '@vitejs/devtools-kit'
22
import type { SharedStatePatch } from '@vitejs/devtools-kit/utils/shared-state'
33
import { anonymousAuth } from './anonymous/auth'
4-
import { docksList } from './internal/docks-list'
54
import { docksOnLaunch } from './internal/docks-on-launch'
65
import { rpcServerList } from './internal/rpc-server-list'
76
import { sharedStateGet } from './internal/state/get'
@@ -25,7 +24,6 @@ export const builtinAnonymousRpcDeclarations = [
2524

2625
// @keep-sorted
2726
export const builtinInternalRpcDeclarations = [
28-
docksList,
2927
docksOnLaunch,
3028
rpcServerList,
3129
sharedStateGet,
@@ -57,12 +55,15 @@ declare module '@vitejs/devtools-kit' {
5755

5856
// @keep-sorted
5957
export interface DevToolsRpcClientFunctions {
60-
'vite:internal:docks:updated': () => Promise<void>
61-
6258
'vite:internal:rpc:client-state:patch': (key: string, patches: SharedStatePatch[], syncId: string) => Promise<void>
6359
'vite:internal:rpc:client-state:updated': (key: string, fullState: any, syncId: string) => Promise<void>
6460

6561
'vite:internal:terminals:stream-chunk': (data: DevToolsTerminalSessionStreamChunkEvent) => Promise<void>
6662
'vite:internal:terminals:updated': () => Promise<void>
6763
}
64+
65+
// @keep-sorted
66+
export interface DevToolsRpcSharedStates {
67+
'vite:internal:docks': DevToolsDockEntry[]
68+
}
6869
}

packages/core/src/node/rpc/internal/docks-list.ts

Lines changed: 0 additions & 31 deletions
This file was deleted.

packages/core/src/node/storage.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ export interface CreateStorageOptions<T extends object> {
88
}
99

1010
export function createStorage<T extends object>(options: CreateStorageOptions<T>) {
11-
let initialState: T
11+
let initialValue: T
1212
if (fs.existsSync(options.filepath)) {
13-
initialState = JSON.parse(fs.readFileSync(options.filepath, 'utf-8')) as T
13+
initialValue = JSON.parse(fs.readFileSync(options.filepath, 'utf-8')) as T
1414
}
1515
else {
16-
initialState = options.initialValue
16+
initialValue = options.initialValue
1717
}
1818

1919
const state = createSharedState<T>({
20-
initialState,
20+
initialValue,
2121
enablePatches: false,
2222
})
2323

packages/kit/src/client/rpc-shared-state.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,27 @@ export function createRpcSharedStateClientHost(rpc: DevToolsRpcClient): RpcShare
5151
if (sharedState.has(key)) {
5252
return sharedState.get(key)!
5353
}
54+
rpc.callEvent('vite:internal:rpc:server-state:subscribe', key)
5455
if (options?.initialValue !== undefined) {
5556
const state = createSharedState<T>({
56-
initialState: options.initialValue,
57+
initialValue: options.initialValue,
5758
enablePatches: false,
5859
})
5960
sharedState.set(key, state)
61+
rpc.call('vite:internal:rpc:server-state:get', key)
62+
.then((serverState) => {
63+
state.mutate(() => serverState)
64+
})
65+
.catch((error) => {
66+
console.error('Error getting server state', error)
67+
})
6068
registerSharedState(key, state)
6169
return state
6270
}
6371
else {
64-
rpc.callEvent('vite:internal:rpc:server-state:subscribe', key)
65-
const initialState = await rpc.call('vite:internal:rpc:server-state:get', key) as T
72+
const initialValue = await rpc.call('vite:internal:rpc:server-state:get', key) as T
6673
const state = createSharedState<T>({
67-
initialState,
74+
initialValue,
6875
enablePatches: false,
6976
})
7077
sharedState.set(key, state)

packages/kit/src/types/docks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export interface DevToolsDockHost {
1010
update: (patch: Partial<T>) => void
1111
}
1212
update: (entry: DevToolsDockUserEntry) => void
13-
values: () => DevToolsDockUserEntry[]
13+
values: () => DevToolsDockEntry[]
1414
}
1515

1616
// TODO: refine categories more clearly

0 commit comments

Comments
 (0)