@vitejs/devtools-kit 0.1.8 → 0.1.9

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.
package/dist/client.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as DevToolsRpcClientCallOptional, a as DevToolsClientRpcHost, b as getDevToolsRpcClient, c as DockEntryStateEvents, d as DocksEntriesContext, f as DocksPanelContext, g as DevToolsRpcClientCallEvent, h as DevToolsRpcClientCall, i as DevToolsClientContext, l as DockPanelStorage, m as DevToolsRpcClient, n as getDevToolsClientContext, o as DockClientType, p as RpcClientEvents, r as DockClientScriptContext, s as DockEntryState, t as CLIENT_CONTEXT_KEY, u as DocksContext, v as DevToolsRpcClientMode, y as DevToolsRpcClientOptions } from "./index-BSLgRVfr.js";
2
- export { CLIENT_CONTEXT_KEY, DevToolsClientContext, DevToolsClientRpcHost, DevToolsRpcClient, DevToolsRpcClientCall, DevToolsRpcClientCallEvent, DevToolsRpcClientCallOptional, DevToolsRpcClientMode, DevToolsRpcClientOptions, DockClientScriptContext, DockClientType, DockEntryState, DockEntryStateEvents, DockPanelStorage, DocksContext, DocksEntriesContext, DocksPanelContext, RpcClientEvents, getDevToolsClientContext, getDevToolsRpcClient };
1
+ import { S as getDevToolsRpcClient, _ as DevToolsRpcClientCall, a as DevToolsClientContext, b as DevToolsRpcClientMode, c as DockEntryState, d as DocksContext, f as DocksEntriesContext, g as DevToolsRpcClient, h as WhenClauseContext, i as CommandsContext, l as DockEntryStateEvents, m as RpcClientEvents, n as getDevToolsClientContext, o as DevToolsClientRpcHost, p as DocksPanelContext, r as DockClientScriptContext, s as DockClientType, t as CLIENT_CONTEXT_KEY, u as DockPanelStorage, v as DevToolsRpcClientCallEvent, x as DevToolsRpcClientOptions, y as DevToolsRpcClientCallOptional } from "./index-BMTnY3zc.js";
2
+ export { CLIENT_CONTEXT_KEY, CommandsContext, DevToolsClientContext, DevToolsClientRpcHost, DevToolsRpcClient, DevToolsRpcClientCall, DevToolsRpcClientCallEvent, DevToolsRpcClientCallOptional, DevToolsRpcClientMode, DevToolsRpcClientOptions, DockClientScriptContext, DockClientType, DockEntryState, DockEntryStateEvents, DockPanelStorage, DocksContext, DocksEntriesContext, DocksPanelContext, RpcClientEvents, WhenClauseContext, getDevToolsClientContext, getDevToolsRpcClient };
@@ -1,4 +1,4 @@
1
- import { D as DevToolsDocksUserSettings } from "./index-BSLgRVfr.js";
1
+ import { k as DevToolsDocksUserSettings } from "./index-BMTnY3zc.js";
2
2
 
3
3
  //#region src/constants.d.ts
4
4
  declare const DEVTOOLS_MOUNT_PATH = "/.devtools/";
@@ -1,5 +1,6 @@
1
1
  import { t as EventEmitter } from "./events-BTCXlxeC.js";
2
- import { o as SharedState } from "./shared-state-NxkOZ3u0.js";
2
+ import { t as WhenContext } from "./when-snfIizvo.js";
3
+ import { o as SharedState } from "./shared-state-CQAciU8Y.js";
3
4
  import { RpcDefinitionsFilter, RpcDefinitionsToFunctions, RpcFunctionsCollector, RpcFunctionsCollectorBase } from "@vitejs/devtools-rpc";
4
5
  import { WebSocketRpcClientOptions } from "@vitejs/devtools-rpc/presets/ws/client";
5
6
  import { DevToolsNodeRpcSessionMeta } from "@vitejs/devtools-rpc/presets/ws/server";
@@ -150,6 +151,127 @@ interface DevToolsLogsHost {
150
151
  clear: () => Promise<void>;
151
152
  }
152
153
  //#endregion
154
+ //#region src/types/commands.d.ts
155
+ interface DevToolsCommandKeybinding {
156
+ /**
157
+ * Keyboard shortcut string.
158
+ * Use "Mod" for platform-aware modifier (Cmd on macOS, Ctrl elsewhere).
159
+ * Examples: "Mod+K", "Mod+Shift+P", "Alt+N"
160
+ */
161
+ key: string;
162
+ }
163
+ interface DevToolsCommandBase {
164
+ /**
165
+ * Unique namespaced ID, e.g. "vite:open-in-editor"
166
+ */
167
+ id: string;
168
+ title: string;
169
+ description?: string;
170
+ /**
171
+ * Iconify icon string, e.g. "ph:pencil-duotone"
172
+ */
173
+ icon?: string;
174
+ category?: string;
175
+ /**
176
+ * Whether to show in command palette. Default: true
177
+ *
178
+ * - `true` — show the command and flatten its children into search results
179
+ * - `false` — hide the command entirely from the palette
180
+ * - `'without-children'` — show the command but don't flatten children into top-level search (children are still accessible via drill-down)
181
+ */
182
+ showInPalette?: boolean | 'without-children';
183
+ /**
184
+ * Optional context expression for conditional visibility.
185
+ * When set, the command is only shown in the palette and only executable
186
+ * when the expression evaluates to true.
187
+ *
188
+ * Uses the same syntax as keybinding `when` clauses.
189
+ * @example 'clientType == embedded'
190
+ * @example 'dockOpen && !paletteOpen'
191
+ */
192
+ when?: string;
193
+ /**
194
+ * Default keyboard shortcut(s) for this command
195
+ */
196
+ keybindings?: DevToolsCommandKeybinding[];
197
+ }
198
+ /**
199
+ * Server command input — what plugins pass to `ctx.commands.register()`.
200
+ */
201
+ interface DevToolsServerCommandInput extends DevToolsCommandBase {
202
+ /**
203
+ * Handler for this command. Optional if the command only serves as a group for children.
204
+ */
205
+ handler?: (...args: any[]) => any | Promise<any>;
206
+ /**
207
+ * Static sub-commands. Two levels max (parent → children).
208
+ * Each child must have a globally unique `id`.
209
+ */
210
+ children?: DevToolsServerCommandInput[];
211
+ }
212
+ /**
213
+ * Serializable server command entry — sent over RPC (no handler).
214
+ */
215
+ interface DevToolsServerCommandEntry extends DevToolsCommandBase {
216
+ source: 'server';
217
+ children?: DevToolsServerCommandEntry[];
218
+ }
219
+ /**
220
+ * Client command — registered in the webcomponent context.
221
+ */
222
+ interface DevToolsClientCommand extends DevToolsCommandBase {
223
+ source: 'client';
224
+ /**
225
+ * Action for this command. Optional if the command only serves as a group for children.
226
+ * Return sub-commands for dynamic nested palette menus (runtime submenus).
227
+ */
228
+ action?: (...args: any[]) => void | DevToolsClientCommand[] | Promise<void | DevToolsClientCommand[]>;
229
+ /**
230
+ * Static sub-commands. Two levels max (parent → children).
231
+ */
232
+ children?: DevToolsClientCommand[];
233
+ }
234
+ /**
235
+ * Union of command entries visible in the palette.
236
+ */
237
+ type DevToolsCommandEntry = DevToolsServerCommandEntry | DevToolsClientCommand;
238
+ interface DevToolsCommandHandle {
239
+ readonly id: string;
240
+ update: (patch: Partial<Omit<DevToolsServerCommandInput, 'id'>>) => void;
241
+ unregister: () => void;
242
+ }
243
+ interface DevToolsCommandsHostEvents {
244
+ 'command:registered': (command: DevToolsServerCommandEntry) => void;
245
+ 'command:unregistered': (id: string) => void;
246
+ }
247
+ interface DevToolsCommandsHost {
248
+ readonly commands: Map<string, DevToolsServerCommandInput>;
249
+ readonly events: EventEmitter<DevToolsCommandsHostEvents>;
250
+ /**
251
+ * Register a command (with optional children).
252
+ */
253
+ register: (command: DevToolsServerCommandInput) => DevToolsCommandHandle;
254
+ /**
255
+ * Unregister a command by ID (removes parent and all children).
256
+ */
257
+ unregister: (id: string) => boolean;
258
+ /**
259
+ * Execute a command by ID. Searches top-level and children.
260
+ * Throws if not found or if command has no handler.
261
+ */
262
+ execute: (id: string, ...args: any[]) => Promise<unknown>;
263
+ /**
264
+ * Returns serializable list (no handlers), preserving tree structure.
265
+ */
266
+ list: () => DevToolsServerCommandEntry[];
267
+ }
268
+ interface DevToolsCommandShortcutOverrides {
269
+ /**
270
+ * Command ID → keybinding overrides. Empty array = shortcut disabled.
271
+ */
272
+ [commandId: string]: DevToolsCommandKeybinding[];
273
+ }
274
+ //#endregion
153
275
  //#region src/types/docks.d.ts
154
276
  interface DevToolsDockHost {
155
277
  readonly views: Map<string, DevToolsDockUserEntry>;
@@ -185,10 +307,16 @@ interface DevToolsDockEntryBase {
185
307
  */
186
308
  category?: DevToolsDockEntryCategory;
187
309
  /**
188
- * Whether the entry should be hidden from the user.
189
- * @default false
310
+ * Conditional visibility expression.
311
+ * When set, the dock entry is only visible when the expression evaluates to true.
312
+ * Uses the same syntax as command `when` clauses.
313
+ *
314
+ * Set to `'false'` to unconditionally hide the entry.
315
+ *
316
+ * @example 'clientType == embedded'
317
+ * @see {@link import('../utils/when').evaluateWhen}
190
318
  */
191
- isHidden?: boolean;
319
+ when?: string;
192
320
  /**
193
321
  * Badge text to display on the dock icon (e.g., unread count)
194
322
  */
@@ -414,6 +542,10 @@ interface DevToolsNodeContext {
414
542
  * Logs host, for emitting and managing structured log entries
415
543
  */
416
544
  logs: DevToolsLogsHost;
545
+ /**
546
+ * Commands host, for registering and executing commands
547
+ */
548
+ commands: DevToolsCommandsHost;
417
549
  /**
418
550
  * Create a JsonRenderer handle for building json-render powered UIs.
419
551
  * Pass the returned handle as `ui` when registering a `json-render` dock entry.
@@ -616,6 +748,21 @@ interface DocksContext extends DevToolsClientContext {
616
748
  * The docks entries context
617
749
  */
618
750
  readonly docks: DocksEntriesContext;
751
+ /**
752
+ * The commands context for command palette and shortcuts
753
+ */
754
+ readonly commands: CommandsContext;
755
+ /**
756
+ * The when-clause context for conditional visibility
757
+ */
758
+ readonly when: WhenClauseContext;
759
+ }
760
+ interface WhenClauseContext {
761
+ /**
762
+ * Get the current when-clause context snapshot.
763
+ * Returns a reactive object with built-in variables and any custom plugin variables.
764
+ */
765
+ readonly context: WhenContext;
619
766
  }
620
767
  type DevToolsClientRpcHost = RpcFunctionsCollector<DevToolsRpcClientFunctions, DevToolsClientContext>;
621
768
  interface DocksPanelContext {
@@ -667,6 +814,36 @@ interface DockEntryStateEvents {
667
814
  interface RpcClientEvents {
668
815
  'rpc:is-trusted:updated': (isTrusted: boolean) => void;
669
816
  }
817
+ interface CommandsContext {
818
+ /**
819
+ * All commands (server + client)
820
+ */
821
+ readonly commands: DevToolsCommandEntry[];
822
+ /**
823
+ * Palette-visible commands only (filtered by `showInPalette !== false`)
824
+ */
825
+ readonly paletteCommands: DevToolsCommandEntry[];
826
+ /**
827
+ * Register client-side command(s). Returns cleanup function.
828
+ */
829
+ register: (cmd: DevToolsClientCommand | DevToolsClientCommand[]) => () => void;
830
+ /**
831
+ * Execute a command by ID. Delegates to RPC for server commands.
832
+ */
833
+ execute: (id: string, ...args: any[]) => Promise<unknown>;
834
+ /**
835
+ * Get effective keybindings for a command (defaults merged with overrides)
836
+ */
837
+ getKeybindings: (id: string) => DevToolsCommandKeybinding[];
838
+ /**
839
+ * Shortcut overrides (persisted via shared state)
840
+ */
841
+ shortcutOverrides: SharedState<DevToolsCommandShortcutOverrides>;
842
+ /**
843
+ * Whether the command palette is open
844
+ */
845
+ paletteOpen: boolean;
846
+ }
670
847
  //#endregion
671
848
  //#region src/client/client-script.d.ts
672
849
  /**
@@ -690,4 +867,4 @@ declare const CLIENT_CONTEXT_KEY = "__VITE_DEVTOOLS_CLIENT_CONTEXT__";
690
867
  */
691
868
  declare function getDevToolsClientContext(): DevToolsClientContext | undefined;
692
869
  //#endregion
693
- export { DevToolsDockEntryBase as $, RpcBroadcastOptions as A, DevToolsChildProcessExecuteOptions as B, PluginWithDevTools as C, DevToolsDocksUserSettings as D, Thenable as E, DevToolsCapabilities as F, DevToolsTerminalSessionStreamChunkEvent as G, DevToolsTerminalHost as H, DevToolsNodeContext as I, DevToolsRpcServerFunctions as J, DevToolsTerminalStatus as K, DevToolsNodeUtils as L, RpcSharedStateGetOptions as M, RpcSharedStateHost as N, DevToolsNodeRpcSession as O, ConnectionMeta as P, DevToolsDockEntry as Q, DevToolsPluginOptions as R, RpcDefinitionsToFunctions as S, DevToolsLogsHost as St, PartialWithoutId as T, DevToolsTerminalSession as U, DevToolsChildProcessTerminalSession as V, DevToolsTerminalSessionBase as W, ClientScriptEntry as X, DevToolsRpcSharedStates as Y, DevToolsDockEntriesGrouped as Z, DevToolsRpcClientCallOptional as _, DevToolsLogEntryInput as _t, DevToolsClientRpcHost as a, DevToolsViewBuiltin as at, getDevToolsRpcClient as b, DevToolsLogLevel as bt, DockEntryStateEvents as c, DevToolsViewJsonRender as ct, DocksEntriesContext as d, JsonRenderElement as dt, DevToolsDockEntryCategory as et, DocksPanelContext as f, JsonRenderSpec as ft, DevToolsRpcClientCallEvent as g, DevToolsLogEntryFrom as gt, DevToolsRpcClientCall as h, DevToolsLogEntry as ht, DevToolsClientContext as i, DevToolsViewAction as it, RpcFunctionsHost as j, DevToolsNodeRpcSessionMeta as k, DockPanelStorage as l, DevToolsViewLauncher as lt, DevToolsRpcClient as m, DevToolsLogElementPosition as mt, getDevToolsClientContext as n, DevToolsDockHost as nt, DockClientType as o, DevToolsViewCustomRender as ot, RpcClientEvents as p, JsonRenderer as pt, DevToolsRpcClientFunctions as q, DockClientScriptContext as r, DevToolsDockUserEntry as rt, DockEntryState as s, DevToolsViewIframe as st, CLIENT_CONTEXT_KEY as t, DevToolsDockEntryIcon as tt, DocksContext as u, DevToolsViewLauncherStatus as ut, DevToolsRpcClientMode as v, DevToolsLogFilePosition as vt, EntriesToObject as w, RpcDefinitionsFilter as x, DevToolsLogsClient as xt, DevToolsRpcClientOptions as y, DevToolsLogHandle as yt, DevToolsViewHost as z };
870
+ export { DevToolsDockEntriesGrouped as $, DevToolsNodeRpcSession as A, DevToolsLogFilePosition as At, DevToolsPluginOptions as B, RpcDefinitionsFilter as C, DevToolsCommandsHostEvents as Ct, PartialWithoutId as D, DevToolsLogEntry as Dt, EntriesToObject as E, DevToolsLogElementPosition as Et, RpcSharedStateHost as F, DevToolsTerminalSession as G, DevToolsChildProcessExecuteOptions as H, ConnectionMeta as I, DevToolsTerminalStatus as J, DevToolsTerminalSessionBase as K, DevToolsCapabilities as L, RpcBroadcastOptions as M, DevToolsLogLevel as Mt, RpcFunctionsHost as N, DevToolsLogsClient as Nt, Thenable as O, DevToolsLogEntryFrom as Ot, RpcSharedStateGetOptions as P, DevToolsLogsHost as Pt, ClientScriptEntry as Q, DevToolsNodeContext as R, getDevToolsRpcClient as S, DevToolsCommandsHost as St, PluginWithDevTools as T, DevToolsServerCommandInput as Tt, DevToolsChildProcessTerminalSession as U, DevToolsViewHost as V, DevToolsTerminalHost as W, DevToolsRpcServerFunctions as X, DevToolsRpcClientFunctions as Y, DevToolsRpcSharedStates as Z, DevToolsRpcClientCall as _, DevToolsCommandBase as _t, DevToolsClientContext as a, DevToolsDockUserEntry as at, DevToolsRpcClientMode as b, DevToolsCommandKeybinding as bt, DockEntryState as c, DevToolsViewCustomRender as ct, DocksContext as d, DevToolsViewLauncher as dt, DevToolsDockEntry as et, DocksEntriesContext as f, DevToolsViewLauncherStatus as ft, DevToolsRpcClient as g, DevToolsClientCommand as gt, WhenClauseContext as h, JsonRenderer as ht, CommandsContext as i, DevToolsDockHost as it, DevToolsNodeRpcSessionMeta as j, DevToolsLogHandle as jt, DevToolsDocksUserSettings as k, DevToolsLogEntryInput as kt, DockEntryStateEvents as l, DevToolsViewIframe as lt, RpcClientEvents as m, JsonRenderSpec as mt, getDevToolsClientContext as n, DevToolsDockEntryCategory as nt, DevToolsClientRpcHost as o, DevToolsViewAction as ot, DocksPanelContext as p, JsonRenderElement as pt, DevToolsTerminalSessionStreamChunkEvent as q, DockClientScriptContext as r, DevToolsDockEntryIcon as rt, DockClientType as s, DevToolsViewBuiltin as st, CLIENT_CONTEXT_KEY as t, DevToolsDockEntryBase as tt, DockPanelStorage as u, DevToolsViewJsonRender as ut, DevToolsRpcClientCallEvent as v, DevToolsCommandEntry as vt, RpcDefinitionsToFunctions as w, DevToolsServerCommandEntry as wt, DevToolsRpcClientOptions as x, DevToolsCommandShortcutOverrides as xt, DevToolsRpcClientCallOptional as y, DevToolsCommandHandle as yt, DevToolsNodeUtils as z };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { n as EventUnsubscribe, r as EventsMap, t as EventEmitter } from "./events-BTCXlxeC.js";
2
- import { $ as DevToolsDockEntryBase, A as RpcBroadcastOptions, B as DevToolsChildProcessExecuteOptions, C as PluginWithDevTools, D as DevToolsDocksUserSettings, E as Thenable, F as DevToolsCapabilities, G as DevToolsTerminalSessionStreamChunkEvent, H as DevToolsTerminalHost, I as DevToolsNodeContext, J as DevToolsRpcServerFunctions, K as DevToolsTerminalStatus, L as DevToolsNodeUtils, M as RpcSharedStateGetOptions, N as RpcSharedStateHost, O as DevToolsNodeRpcSession, P as ConnectionMeta, Q as DevToolsDockEntry, R as DevToolsPluginOptions, S as RpcDefinitionsToFunctions, St as DevToolsLogsHost, T as PartialWithoutId, U as DevToolsTerminalSession, V as DevToolsChildProcessTerminalSession, W as DevToolsTerminalSessionBase, X as ClientScriptEntry, Y as DevToolsRpcSharedStates, Z as DevToolsDockEntriesGrouped, _t as DevToolsLogEntryInput, at as DevToolsViewBuiltin, bt as DevToolsLogLevel, ct as DevToolsViewJsonRender, dt as JsonRenderElement, et as DevToolsDockEntryCategory, ft as JsonRenderSpec, gt as DevToolsLogEntryFrom, ht as DevToolsLogEntry, it as DevToolsViewAction, j as RpcFunctionsHost, k as DevToolsNodeRpcSessionMeta, lt as DevToolsViewLauncher, mt as DevToolsLogElementPosition, nt as DevToolsDockHost, ot as DevToolsViewCustomRender, pt as JsonRenderer, q as DevToolsRpcClientFunctions, rt as DevToolsDockUserEntry, st as DevToolsViewIframe, tt as DevToolsDockEntryIcon, ut as DevToolsViewLauncherStatus, vt as DevToolsLogFilePosition, w as EntriesToObject, x as RpcDefinitionsFilter, xt as DevToolsLogsClient, yt as DevToolsLogHandle, z as DevToolsViewHost } from "./index-BSLgRVfr.js";
2
+ import { $ as DevToolsDockEntriesGrouped, A as DevToolsNodeRpcSession, At as DevToolsLogFilePosition, B as DevToolsPluginOptions, C as RpcDefinitionsFilter, Ct as DevToolsCommandsHostEvents, D as PartialWithoutId, Dt as DevToolsLogEntry, E as EntriesToObject, Et as DevToolsLogElementPosition, F as RpcSharedStateHost, G as DevToolsTerminalSession, H as DevToolsChildProcessExecuteOptions, I as ConnectionMeta, J as DevToolsTerminalStatus, K as DevToolsTerminalSessionBase, L as DevToolsCapabilities, M as RpcBroadcastOptions, Mt as DevToolsLogLevel, N as RpcFunctionsHost, Nt as DevToolsLogsClient, O as Thenable, Ot as DevToolsLogEntryFrom, P as RpcSharedStateGetOptions, Pt as DevToolsLogsHost, Q as ClientScriptEntry, R as DevToolsNodeContext, St as DevToolsCommandsHost, T as PluginWithDevTools, Tt as DevToolsServerCommandInput, U as DevToolsChildProcessTerminalSession, V as DevToolsViewHost, W as DevToolsTerminalHost, X as DevToolsRpcServerFunctions, Y as DevToolsRpcClientFunctions, Z as DevToolsRpcSharedStates, _t as DevToolsCommandBase, at as DevToolsDockUserEntry, bt as DevToolsCommandKeybinding, ct as DevToolsViewCustomRender, dt as DevToolsViewLauncher, et as DevToolsDockEntry, ft as DevToolsViewLauncherStatus, gt as DevToolsClientCommand, ht as JsonRenderer, it as DevToolsDockHost, j as DevToolsNodeRpcSessionMeta, jt as DevToolsLogHandle, k as DevToolsDocksUserSettings, kt as DevToolsLogEntryInput, lt as DevToolsViewIframe, mt as JsonRenderSpec, nt as DevToolsDockEntryCategory, ot as DevToolsViewAction, pt as JsonRenderElement, q as DevToolsTerminalSessionStreamChunkEvent, rt as DevToolsDockEntryIcon, st as DevToolsViewBuiltin, tt as DevToolsDockEntryBase, ut as DevToolsViewJsonRender, vt as DevToolsCommandEntry, w as RpcDefinitionsToFunctions, wt as DevToolsServerCommandEntry, xt as DevToolsCommandShortcutOverrides, yt as DevToolsCommandHandle, z as DevToolsNodeUtils } from "./index-BMTnY3zc.js";
3
+ import { t as WhenContext } from "./when-snfIizvo.js";
3
4
  import * as _vitejs_devtools_rpc0 from "@vitejs/devtools-rpc";
4
5
 
5
- //#region src/utils/define.d.ts
6
+ //#region src/define.d.ts
6
7
  declare const defineRpcFunction: <NAME extends string, TYPE extends _vitejs_devtools_rpc0.RpcFunctionType, ARGS extends any[], RETURN = void, const AS extends _vitejs_devtools_rpc0.RpcArgsSchema | undefined = undefined, const RS extends _vitejs_devtools_rpc0.RpcReturnSchema | undefined = undefined>(definition: _vitejs_devtools_rpc0.RpcFunctionDefinition<NAME, TYPE, ARGS, RETURN, AS, RS, DevToolsNodeContext>) => _vitejs_devtools_rpc0.RpcFunctionDefinition<NAME, TYPE, ARGS, RETURN, AS, RS, DevToolsNodeContext>;
7
- //#endregion
8
- //#region src/utils/json-render.d.ts
8
+ declare function defineCommand(command: DevToolsServerCommandInput): DevToolsServerCommandInput;
9
9
  declare function defineJsonRenderSpec(spec: JsonRenderSpec): JsonRenderSpec;
10
10
  //#endregion
11
- export { ClientScriptEntry, ConnectionMeta, DevToolsCapabilities, DevToolsChildProcessExecuteOptions, DevToolsChildProcessTerminalSession, DevToolsDockEntriesGrouped, DevToolsDockEntry, DevToolsDockEntryBase, DevToolsDockEntryCategory, DevToolsDockEntryIcon, DevToolsDockHost, DevToolsDockUserEntry, DevToolsDocksUserSettings, DevToolsLogElementPosition, DevToolsLogEntry, DevToolsLogEntryFrom, DevToolsLogEntryInput, DevToolsLogFilePosition, DevToolsLogHandle, DevToolsLogLevel, DevToolsLogsClient, DevToolsLogsHost, DevToolsNodeContext, DevToolsNodeRpcSession, DevToolsNodeRpcSessionMeta, DevToolsNodeUtils, DevToolsPluginOptions, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions, DevToolsRpcSharedStates, DevToolsTerminalHost, DevToolsTerminalSession, DevToolsTerminalSessionBase, DevToolsTerminalSessionStreamChunkEvent, DevToolsTerminalStatus, DevToolsViewAction, DevToolsViewBuiltin, DevToolsViewCustomRender, DevToolsViewHost, DevToolsViewIframe, DevToolsViewJsonRender, DevToolsViewLauncher, DevToolsViewLauncherStatus, EntriesToObject, EventEmitter, EventUnsubscribe, EventsMap, JsonRenderElement, JsonRenderSpec, JsonRenderer, PartialWithoutId, PluginWithDevTools, RpcBroadcastOptions, RpcDefinitionsFilter, RpcDefinitionsToFunctions, RpcFunctionsHost, RpcSharedStateGetOptions, RpcSharedStateHost, Thenable, defineJsonRenderSpec, defineRpcFunction };
11
+ export { ClientScriptEntry, ConnectionMeta, DevToolsCapabilities, DevToolsChildProcessExecuteOptions, DevToolsChildProcessTerminalSession, DevToolsClientCommand, DevToolsCommandBase, DevToolsCommandEntry, DevToolsCommandHandle, DevToolsCommandKeybinding, DevToolsCommandShortcutOverrides, DevToolsCommandsHost, DevToolsCommandsHostEvents, DevToolsDockEntriesGrouped, DevToolsDockEntry, DevToolsDockEntryBase, DevToolsDockEntryCategory, DevToolsDockEntryIcon, DevToolsDockHost, DevToolsDockUserEntry, DevToolsDocksUserSettings, DevToolsLogElementPosition, DevToolsLogEntry, DevToolsLogEntryFrom, DevToolsLogEntryInput, DevToolsLogFilePosition, DevToolsLogHandle, DevToolsLogLevel, DevToolsLogsClient, DevToolsLogsHost, DevToolsNodeContext, DevToolsNodeRpcSession, DevToolsNodeRpcSessionMeta, DevToolsNodeUtils, DevToolsPluginOptions, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions, DevToolsRpcSharedStates, DevToolsServerCommandEntry, DevToolsServerCommandInput, DevToolsTerminalHost, DevToolsTerminalSession, DevToolsTerminalSessionBase, DevToolsTerminalSessionStreamChunkEvent, DevToolsTerminalStatus, DevToolsViewAction, DevToolsViewBuiltin, DevToolsViewCustomRender, DevToolsViewHost, DevToolsViewIframe, DevToolsViewJsonRender, DevToolsViewLauncher, DevToolsViewLauncherStatus, EntriesToObject, EventEmitter, EventUnsubscribe, EventsMap, JsonRenderElement, JsonRenderSpec, JsonRenderer, PartialWithoutId, PluginWithDevTools, RpcBroadcastOptions, RpcDefinitionsFilter, RpcDefinitionsToFunctions, RpcFunctionsHost, RpcSharedStateGetOptions, RpcSharedStateHost, Thenable, WhenContext, defineCommand, defineJsonRenderSpec, defineRpcFunction };
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { createDefineWrapperWithContext } from "@vitejs/devtools-rpc";
2
- //#region src/utils/define.ts
2
+ //#region src/define.ts
3
3
  const defineRpcFunction = createDefineWrapperWithContext();
4
- //#endregion
5
- //#region src/utils/json-render.ts
4
+ function defineCommand(command) {
5
+ return command;
6
+ }
6
7
  function defineJsonRenderSpec(spec) {
7
8
  return spec;
8
9
  }
9
10
  //#endregion
10
- export { defineJsonRenderSpec, defineRpcFunction };
11
+ export { defineCommand, defineJsonRenderSpec, defineRpcFunction };
@@ -1,2 +1,2 @@
1
- import { a as ImmutableSet, c as SharedStateOptions, i as ImmutableObject, l as createSharedState, n as ImmutableArray, o as SharedState, r as ImmutableMap, s as SharedStateEvents, t as Immutable, u as Patch } from "../shared-state-NxkOZ3u0.js";
1
+ import { a as ImmutableSet, c as SharedStateOptions, i as ImmutableObject, l as createSharedState, n as ImmutableArray, o as SharedState, r as ImmutableMap, s as SharedStateEvents, t as Immutable, u as Patch } from "../shared-state-CQAciU8Y.js";
2
2
  export { Immutable, ImmutableArray, ImmutableMap, ImmutableObject, ImmutableSet, SharedState, SharedStateEvents, SharedStateOptions, Patch as SharedStatePatch, createSharedState };
@@ -0,0 +1,2 @@
1
+ import { n as evaluateWhen, r as getContextValue, t as WhenContext } from "../when-snfIizvo.js";
2
+ export { WhenContext, evaluateWhen, getContextValue };
@@ -0,0 +1,66 @@
1
+ //#region src/utils/when.ts
2
+ /**
3
+ * Evaluate a `when` expression against a context object.
4
+ *
5
+ * Supported syntax:
6
+ * - Bare truthy: `dockOpen` → true if value is truthy
7
+ * - Literal booleans: `true`, `false`
8
+ * - Negation: `!paletteOpen`
9
+ * - Equality: `clientType == embedded`
10
+ * - Inequality: `clientType != standalone`
11
+ * - AND: `dockOpen && !paletteOpen`
12
+ * - OR: `paletteOpen || dockOpen`
13
+ * - Namespaced keys: `vite.mode == development`, `vite:buildMode`
14
+ *
15
+ * Precedence: `||` (lowest) → `&&` → unary `!`
16
+ */
17
+ function evaluateWhen(expression, ctx) {
18
+ return expression.split("||").map((s) => s.trim()).some((orPart) => {
19
+ return orPart.split("&&").map((s) => s.trim()).every((part) => {
20
+ const trimmed = part.trim();
21
+ if (trimmed === "true") return true;
22
+ if (trimmed === "false") return false;
23
+ if (trimmed.startsWith("!")) {
24
+ const key = trimmed.slice(1).trim();
25
+ if (key === "true") return false;
26
+ if (key === "false") return true;
27
+ return !getContextValue(key, ctx);
28
+ }
29
+ const eqIdx = trimmed.indexOf("==");
30
+ const neqIdx = trimmed.indexOf("!=");
31
+ if (eqIdx !== -1 || neqIdx !== -1) {
32
+ const isNeq = neqIdx !== -1 && (eqIdx === -1 || neqIdx < eqIdx);
33
+ const opIdx = isNeq ? neqIdx : eqIdx;
34
+ const opLen = isNeq ? 2 : 2;
35
+ const key = trimmed.slice(0, opIdx).trim();
36
+ const value = trimmed.slice(opIdx + opLen).trim();
37
+ const actual = String(getContextValue(key, ctx));
38
+ return isNeq ? actual !== value : actual === value;
39
+ }
40
+ return !!getContextValue(trimmed, ctx);
41
+ });
42
+ });
43
+ }
44
+ /**
45
+ * Get a context value by key. Supports namespaced keys with `.` or `:` separators.
46
+ *
47
+ * Lookup order:
48
+ * 1. Exact match — `ctx['vite.mode']` or `ctx['vite:mode']`
49
+ * 2. Nested path — for `vite.mode`: `ctx.vite?.mode`; for `vite:mode`: `ctx.vite?.mode`
50
+ */
51
+ function getContextValue(key, ctx) {
52
+ const record = ctx;
53
+ if (key in record) return record[key];
54
+ const separator = key.includes(".") ? "." : key.includes(":") ? ":" : null;
55
+ if (separator) {
56
+ const segments = key.split(separator);
57
+ let current = record;
58
+ for (const segment of segments) {
59
+ if (current == null || typeof current !== "object") return void 0;
60
+ current = current[segment];
61
+ }
62
+ return current;
63
+ }
64
+ }
65
+ //#endregion
66
+ export { evaluateWhen, getContextValue };
@@ -0,0 +1,47 @@
1
+ //#region src/utils/when.d.ts
2
+ /**
3
+ * Context object for evaluating `when` expressions.
4
+ *
5
+ * Built-in variables:
6
+ * - `clientType` — `'embedded' | 'standalone'`
7
+ * - `dockOpen` — whether the dock panel is open
8
+ * - `paletteOpen` — whether the command palette is open
9
+ * - `dockSelectedId` — ID of the selected dock entry (empty string if none)
10
+ *
11
+ * Plugins can add namespaced variables using dot or colon separators:
12
+ * - `vite.mode`, `vite:mode` — stored as `{ 'vite.mode': 'development' }` or nested `{ vite: { mode: 'development' } }`
13
+ */
14
+ interface WhenContext {
15
+ clientType: 'embedded' | 'standalone';
16
+ dockOpen: boolean;
17
+ paletteOpen: boolean;
18
+ dockSelectedId: string;
19
+ /** Allow custom context variables from plugins */
20
+ [key: string]: unknown;
21
+ }
22
+ /**
23
+ * Evaluate a `when` expression against a context object.
24
+ *
25
+ * Supported syntax:
26
+ * - Bare truthy: `dockOpen` → true if value is truthy
27
+ * - Literal booleans: `true`, `false`
28
+ * - Negation: `!paletteOpen`
29
+ * - Equality: `clientType == embedded`
30
+ * - Inequality: `clientType != standalone`
31
+ * - AND: `dockOpen && !paletteOpen`
32
+ * - OR: `paletteOpen || dockOpen`
33
+ * - Namespaced keys: `vite.mode == development`, `vite:buildMode`
34
+ *
35
+ * Precedence: `||` (lowest) → `&&` → unary `!`
36
+ */
37
+ declare function evaluateWhen(expression: string, ctx: WhenContext): boolean;
38
+ /**
39
+ * Get a context value by key. Supports namespaced keys with `.` or `:` separators.
40
+ *
41
+ * Lookup order:
42
+ * 1. Exact match — `ctx['vite.mode']` or `ctx['vite:mode']`
43
+ * 2. Nested path — for `vite.mode`: `ctx.vite?.mode`; for `vite:mode`: `ctx.vite?.mode`
44
+ */
45
+ declare function getContextValue(key: string, ctx: WhenContext): unknown;
46
+ //#endregion
47
+ export { evaluateWhen as n, getContextValue as r, WhenContext as t };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitejs/devtools-kit",
3
3
  "type": "module",
4
- "version": "0.1.8",
4
+ "version": "0.1.9",
5
5
  "description": "Vite DevTools Kit",
6
6
  "author": "VoidZero Inc.",
7
7
  "license": "MIT",
@@ -26,6 +26,7 @@
26
26
  "./utils/human-id": "./dist/utils/human-id.js",
27
27
  "./utils/nanoid": "./dist/utils/nanoid.js",
28
28
  "./utils/shared-state": "./dist/utils/shared-state.js",
29
+ "./utils/when": "./dist/utils/when.js",
29
30
  "./package.json": "./package.json"
30
31
  },
31
32
  "types": "./dist/index.d.mts",
@@ -39,14 +40,14 @@
39
40
  "dependencies": {
40
41
  "birpc": "^4.0.0",
41
42
  "ohash": "^2.0.11",
42
- "@vitejs/devtools-rpc": "0.1.8"
43
+ "@vitejs/devtools-rpc": "0.1.9"
43
44
  },
44
45
  "devDependencies": {
45
46
  "human-id": "^4.1.3",
46
47
  "immer": "^11.1.4",
47
48
  "tsdown": "^0.21.4",
48
49
  "ua-parser-modern": "^0.1.1",
49
- "vite": "^8.0.1"
50
+ "vite": "^8.0.2"
50
51
  },
51
52
  "inlinedDependencies": {
52
53
  "human-id": "4.1.3",
@@ -25,6 +25,7 @@ A DevTools plugin extends a Vite plugin with a `devtools.setup(ctx)` hook. The c
25
25
  | `ctx.logs` | Emit structured log entries and toast notifications |
26
26
  | `ctx.terminals` | Spawn and manage child processes with streaming terminal output |
27
27
  | `ctx.createJsonRenderer` | Create server-side JSON render specs for zero-client-code UIs |
28
+ | `ctx.commands` | Register executable commands with keyboard shortcuts and palette visibility |
28
29
  | `ctx.viteConfig` | Resolved Vite configuration |
29
30
  | `ctx.viteServer` | Dev server instance (dev mode only) |
30
31
  | `ctx.mode` | `'dev'` or `'build'` |
@@ -107,12 +108,13 @@ export default function myAnalyzer(): Plugin {
107
108
 
108
109
  ## Namespacing Convention
109
110
 
110
- **CRITICAL**: Always prefix RPC functions, shared state keys, and dock IDs with your plugin name:
111
+ **CRITICAL**: Always prefix RPC functions, shared state keys, dock IDs, and command IDs with your plugin name:
111
112
 
112
113
  ```ts
113
114
  // Good - namespaced
114
115
  'my-plugin:get-modules'
115
116
  'my-plugin:state'
117
+ 'my-plugin:clear-cache' // command ID
116
118
 
117
119
  // Bad - may conflict
118
120
  'get-modules'
@@ -254,6 +256,27 @@ await session.restart()
254
256
 
255
257
  A common pattern is combining with launcher docks — see [Terminals Patterns](./references/terminals-patterns.md).
256
258
 
259
+ ## Commands & Command Palette
260
+
261
+ Register executable commands discoverable via `Mod+K` palette:
262
+
263
+ ```ts
264
+ import { defineCommand } from '@vitejs/devtools-kit'
265
+
266
+ ctx.commands.register(defineCommand({
267
+ id: 'my-plugin:clear-cache',
268
+ title: 'Clear Build Cache',
269
+ icon: 'ph:trash-duotone',
270
+ keybindings: [{ key: 'Mod+Shift+C' }],
271
+ when: 'clientType == embedded',
272
+ handler: async () => { /* ... */ },
273
+ }))
274
+ ```
275
+
276
+ Commands support sub-commands (two-level hierarchy), conditional visibility via `when` clauses, and user-customizable keyboard shortcuts.
277
+
278
+ See [Commands Patterns](./references/commands-patterns.md) and [When Clauses](./references/when-clauses.md) for full details.
279
+
257
280
  ## Logs & Notifications
258
281
 
259
282
  Plugins can emit structured log entries from both server and client contexts. Logs appear in the built-in **Logs** panel and can optionally show as toast notifications.
@@ -498,6 +521,8 @@ export default defineConfig({
498
521
  6. **Use Iconify icons** - Prefer `ph:*` (Phosphor) icons: `icon: 'ph:chart-bar-duotone'`
499
522
  7. **Deduplicate logs** - Use explicit `id` for logs representing ongoing operations
500
523
  8. **Use Self-Inspect** - Add `@vitejs/devtools-self-inspect` during development to debug your plugin
524
+ 9. **Namespace command IDs** - Use `my-plugin:action` pattern for command IDs, same as RPC and state
525
+ 10. **Use `when` clauses** - Conditionally show commands/docks with `when` expressions instead of programmatic show/hide
501
526
 
502
527
  ## Example Plugins
503
528
 
@@ -516,3 +541,5 @@ Real-world example plugins in the repo — reference their code structure and pa
516
541
  - [JSON Render Patterns](./references/json-render-patterns.md) - Server-side JSON specs, components, state binding
517
542
  - [Terminals Patterns](./references/terminals-patterns.md) - Child processes, custom streams, session lifecycle
518
543
  - [Logs Patterns](./references/logs-patterns.md) - Log entries, toast notifications, and handle patterns
544
+ - [Commands Patterns](./references/commands-patterns.md) - Command registration, sub-commands, keybindings, palette integration
545
+ - [When Clauses](./references/when-clauses.md) - Conditional expression syntax, context variables, API reference
@@ -0,0 +1,241 @@
1
+ # Commands & Command Palette
2
+
3
+ Register executable commands discoverable through a built-in palette with keyboard shortcuts.
4
+
5
+ ## Defining Commands
6
+
7
+ ```ts
8
+ import { defineCommand } from '@vitejs/devtools-kit'
9
+
10
+ const clearCache = defineCommand({
11
+ id: 'my-plugin:clear-cache',
12
+ title: 'Clear Build Cache',
13
+ description: 'Remove all cached build artifacts',
14
+ icon: 'ph:trash-duotone',
15
+ category: 'tools',
16
+ handler: async () => {
17
+ await fs.rm('.cache', { recursive: true })
18
+ },
19
+ })
20
+
21
+ // Register in plugin setup
22
+ ctx.commands.register(clearCache)
23
+ ```
24
+
25
+ ## Command Options
26
+
27
+ | Field | Type | Description |
28
+ |-------|------|-------------|
29
+ | `id` | `string` | **Required.** Unique namespaced ID (e.g. `my-plugin:action`) |
30
+ | `title` | `string` | **Required.** Human-readable title shown in the palette |
31
+ | `description` | `string` | Optional description text |
32
+ | `icon` | `string` | Iconify icon string (e.g. `ph:trash-duotone`) |
33
+ | `category` | `string` | Category for grouping |
34
+ | `showInPalette` | `boolean \| 'without-children'` | Whether to show in command palette (default: `true`). `'without-children'` shows the command but doesn't flatten children into search — only accessible via drill-down. |
35
+ | `when` | `string` | Conditional visibility expression — see [When Clauses](./when-clauses.md) |
36
+ | `keybindings` | `DevToolsCommandKeybinding[]` | Default keyboard shortcuts |
37
+ | `handler` | `Function` | Server-side handler. Optional if the command is a group for children. |
38
+ | `children` | `DevToolsServerCommandInput[]` | Static sub-commands (two levels max) |
39
+
40
+ ## Command Handle
41
+
42
+ `register()` returns a handle for live updates:
43
+
44
+ ```ts
45
+ const handle = ctx.commands.register({
46
+ id: 'my-plugin:status',
47
+ title: 'Show Status',
48
+ handler: () => { /* ... */ },
49
+ })
50
+
51
+ // Update later
52
+ handle.update({ title: 'Show Status (3 items)' })
53
+
54
+ // Remove
55
+ handle.unregister()
56
+ ```
57
+
58
+ ## Sub-Commands
59
+
60
+ Two-level hierarchy. Selecting a parent in the palette drills down into its children.
61
+
62
+ ```ts
63
+ ctx.commands.register({
64
+ id: 'git',
65
+ title: 'Git',
66
+ icon: 'ph:git-branch-duotone',
67
+ category: 'tools',
68
+ // No handler — group-only parent
69
+ children: [
70
+ {
71
+ id: 'git:commit',
72
+ title: 'Commit',
73
+ icon: 'ph:check-duotone',
74
+ keybindings: [{ key: 'Mod+Shift+G' }],
75
+ handler: async () => { /* ... */ },
76
+ },
77
+ {
78
+ id: 'git:push',
79
+ title: 'Push',
80
+ handler: async () => { /* ... */ },
81
+ },
82
+ ],
83
+ })
84
+ ```
85
+
86
+ Each child must have a globally unique `id`. Use the pattern `parentId:childAction` (e.g. `git:commit`).
87
+
88
+ Sub-commands with keybindings can be executed directly via the shortcut without opening the palette.
89
+
90
+ ## Keyboard Shortcuts
91
+
92
+ ### Key Format
93
+
94
+ Use `Mod` as a platform-aware modifier — maps to `Cmd` on macOS and `Ctrl` on other platforms.
95
+
96
+ | Key string | macOS | Windows/Linux |
97
+ |------------|-------|---------------|
98
+ | `Mod+K` | `Cmd+K` | `Ctrl+K` |
99
+ | `Mod+Shift+P` | `Cmd+Shift+P` | `Ctrl+Shift+P` |
100
+ | `Alt+N` | `Option+N` | `Alt+N` |
101
+
102
+ ```ts
103
+ ctx.commands.register(defineCommand({
104
+ id: 'my-plugin:toggle-overlay',
105
+ title: 'Toggle Overlay',
106
+ keybindings: [{ key: 'Mod+Shift+O' }],
107
+ handler: () => { /* ... */ },
108
+ }))
109
+ ```
110
+
111
+ ### User Overrides
112
+
113
+ Users can customize shortcuts in Settings > **Keyboard Shortcuts**. Overrides persist across sessions. Setting an empty array disables a shortcut.
114
+
115
+ The shortcut editor includes:
116
+ - **Key capture** — click the input and press any key combination
117
+ - **Modifier toggles** — toggle Cmd/Ctrl, Alt, Shift individually
118
+ - **Conflict detection** — warns on browser shortcut conflicts, duplicate bindings, and weak shortcuts (single key without modifiers)
119
+
120
+ `KNOWN_BROWSER_SHORTCUTS` is exported from `@vitejs/devtools-kit` and maps key combinations to human-readable descriptions.
121
+
122
+ ## Conditional Visibility
123
+
124
+ Commands support a `when` expression for conditional visibility:
125
+
126
+ ```ts
127
+ ctx.commands.register(defineCommand({
128
+ id: 'my-plugin:embedded-only',
129
+ title: 'Embedded-Only Action',
130
+ when: 'clientType == embedded',
131
+ handler: async () => { /* ... */ },
132
+ }))
133
+ ```
134
+
135
+ When set, the command only appears in the palette and is only triggerable via shortcuts when the expression evaluates to `true`.
136
+
137
+ See [When Clauses](./when-clauses.md) for full syntax reference and context variables.
138
+
139
+ ## Client-Side Commands
140
+
141
+ Client commands register in the webcomponent context and execute directly in the browser:
142
+
143
+ ```ts
144
+ context.commands.register({
145
+ id: 'devtools:theme',
146
+ source: 'client',
147
+ title: 'Theme',
148
+ icon: 'ph:palette-duotone',
149
+ children: [
150
+ {
151
+ id: 'devtools:theme:light',
152
+ source: 'client',
153
+ title: 'Light',
154
+ action: () => setTheme('light'),
155
+ },
156
+ {
157
+ id: 'devtools:theme:dark',
158
+ source: 'client',
159
+ title: 'Dark',
160
+ action: () => setTheme('dark'),
161
+ },
162
+ ],
163
+ })
164
+ ```
165
+
166
+ Client commands can return dynamic sub-items:
167
+
168
+ ```ts
169
+ context.commands.register({
170
+ id: 'devtools:docs',
171
+ source: 'client',
172
+ title: 'Documentation',
173
+ action: async () => {
174
+ const docs = await fetchDocs()
175
+ return docs.map(doc => ({
176
+ id: `docs:${doc.slug}`,
177
+ source: 'client' as const,
178
+ title: doc.title,
179
+ action: () => window.open(doc.url, '_blank'),
180
+ }))
181
+ },
182
+ })
183
+ ```
184
+
185
+ ## Command Palette
186
+
187
+ Built-in palette toggled with `Mod+K`. Features:
188
+
189
+ - **Fuzzy search** across all registered commands (including sub-commands)
190
+ - **Keyboard navigation** — Arrow keys, Enter to select, Escape to close
191
+ - **Drill-down** — Commands with children show breadcrumb navigation
192
+ - **Server command execution** — via RPC with loading indicator
193
+ - **Dynamic sub-menus** — Client commands can return sub-items at runtime
194
+
195
+ ## Complete Example
196
+
197
+ ```ts
198
+ /// <reference types="@vitejs/devtools-kit" />
199
+ import type { Plugin } from 'vite'
200
+ import { defineCommand } from '@vitejs/devtools-kit'
201
+
202
+ export default function myPlugin(): Plugin {
203
+ return {
204
+ name: 'my-plugin',
205
+
206
+ devtools: {
207
+ setup(ctx) {
208
+ // Simple command with keybinding
209
+ ctx.commands.register(defineCommand({
210
+ id: 'my-plugin:restart',
211
+ title: 'Restart Dev Server',
212
+ icon: 'ph:arrow-clockwise-duotone',
213
+ keybindings: [{ key: 'Mod+Shift+R' }],
214
+ handler: async () => {
215
+ await ctx.viteServer?.restart()
216
+ },
217
+ }))
218
+
219
+ // Command group with sub-commands
220
+ ctx.commands.register(defineCommand({
221
+ id: 'my-plugin:cache',
222
+ title: 'Cache',
223
+ icon: 'ph:database-duotone',
224
+ children: [
225
+ {
226
+ id: 'my-plugin:cache:clear',
227
+ title: 'Clear Cache',
228
+ handler: async () => { /* ... */ },
229
+ },
230
+ {
231
+ id: 'my-plugin:cache:inspect',
232
+ title: 'Inspect Cache',
233
+ handler: async () => { /* ... */ },
234
+ },
235
+ ],
236
+ }))
237
+ },
238
+ },
239
+ }
240
+ }
241
+ ```
@@ -13,7 +13,7 @@ interface DockEntryBase {
13
13
  icon: string // URL, data URI, or Iconify name
14
14
  category?: string // Grouping category
15
15
  defaultOrder?: number // Sort order (higher = earlier)
16
- isHidden?: boolean // Hide from dock
16
+ when?: string // Conditional visibility expression — see [When Clauses](./when-clauses.md)
17
17
  badge?: string // Badge text on dock icon (e.g., count)
18
18
  }
19
19
  ```
@@ -0,0 +1,160 @@
1
+ # When Clauses
2
+
3
+ Conditional expressions controlling visibility and activation of commands and dock entries.
4
+
5
+ ## Usage
6
+
7
+ ### On Commands
8
+
9
+ Controls whether the command appears in the palette and can be triggered via shortcuts:
10
+
11
+ ```ts
12
+ ctx.commands.register(defineCommand({
13
+ id: 'my-plugin:embedded-only',
14
+ title: 'Embedded-Only Action',
15
+ when: 'clientType == embedded',
16
+ handler: async () => { /* ... */ },
17
+ }))
18
+ ```
19
+
20
+ ### On Dock Entries
21
+
22
+ Controls whether a dock entry is visible in the dock bar:
23
+
24
+ ```ts
25
+ ctx.docks.register({
26
+ id: 'my-plugin:inspector',
27
+ title: 'Inspector',
28
+ type: 'action',
29
+ icon: 'ph:cursor-duotone',
30
+ when: 'clientType == embedded',
31
+ action: { importFrom: 'my-plugin/inspector' },
32
+ })
33
+ ```
34
+
35
+ Set `when: 'false'` to unconditionally hide a dock entry.
36
+
37
+ ## Expression Syntax
38
+
39
+ ### Operators
40
+
41
+ | Operator | Example | Description |
42
+ |----------|---------|-------------|
43
+ | bare truthy | `dockOpen` | True if the value is truthy |
44
+ | `true` / `false` | `true` | Literal boolean values |
45
+ | `!` | `!paletteOpen` | Negation |
46
+ | `==` | `clientType == embedded` | Equality (string comparison) |
47
+ | `!=` | `clientType != standalone` | Inequality |
48
+ | `&&` | `dockOpen && !paletteOpen` | Logical AND |
49
+ | `\|\|` | `paletteOpen \|\| dockOpen` | Logical OR |
50
+
51
+ ### Precedence
52
+
53
+ `||` (lowest) → `&&` → unary `!`
54
+
55
+ Each `||` branch is evaluated as a chain of `&&` parts: `a && b || c && d` = `(a AND b) OR (c AND d)`.
56
+
57
+ ### Examples
58
+
59
+ ```ts
60
+ // Always visible
61
+ when: 'true'
62
+
63
+ // Never visible (unconditionally hidden)
64
+ when: 'false'
65
+
66
+ // Only in embedded mode
67
+ when: 'clientType == embedded'
68
+
69
+ // Only when dock is open and palette is closed
70
+ when: 'dockOpen && !paletteOpen'
71
+
72
+ // When a specific dock is selected
73
+ when: 'dockSelectedId == my-plugin'
74
+
75
+ // Plugin-specific context
76
+ when: 'vite.mode == development'
77
+
78
+ // Compound: either in embedded with dock open, or in standalone
79
+ when: 'clientType == embedded && dockOpen || clientType == standalone'
80
+ ```
81
+
82
+ ## Built-in Context Variables
83
+
84
+ | Variable | Type | Description |
85
+ |----------|------|-------------|
86
+ | `clientType` | `'embedded' \| 'standalone'` | Current client mode |
87
+ | `dockOpen` | `boolean` | Whether the dock panel is currently open |
88
+ | `paletteOpen` | `boolean` | Whether the command palette is currently open |
89
+ | `dockSelectedId` | `string` | ID of the currently selected dock entry. Empty string (falsy) when none selected. |
90
+
91
+ ## Namespaced Context Keys
92
+
93
+ Plugins can register context variables using namespaced keys with `.` or `:` separators:
94
+
95
+ ```ts
96
+ // Flat key (recommended)
97
+ context['vite.mode'] = 'development'
98
+ context['vite:buildMode'] = 'lib'
99
+
100
+ // Nested object (also supported)
101
+ context.vite = { mode: 'development', ssr: true }
102
+ ```
103
+
104
+ Both styles work in `when` expressions:
105
+
106
+ ```ts
107
+ when: 'vite.mode == development'
108
+ when: 'vite:buildMode == lib'
109
+ when: 'vite.ssr'
110
+ ```
111
+
112
+ ### Lookup Order
113
+
114
+ When resolving a namespaced key like `vite.mode`:
115
+
116
+ 1. **Exact match** — looks for `ctx['vite.mode']` first
117
+ 2. **Nested path** — falls back to `ctx.vite?.mode`
118
+
119
+ Flat keys take priority over nested objects if both exist. Use your plugin name as namespace prefix: `my-plugin.featureEnabled`, `rolldown:buildStep`.
120
+
121
+ ## API Reference
122
+
123
+ ```ts
124
+ import type { WhenContext } from '@vitejs/devtools-kit'
125
+ import { evaluateWhen, getContextValue } from '@vitejs/devtools-kit/utils/when'
126
+
127
+ const ctx: WhenContext = {
128
+ 'clientType': 'embedded',
129
+ 'dockOpen': true,
130
+ 'paletteOpen': false,
131
+ 'dockSelectedId': 'my-dock',
132
+ 'vite.mode': 'development',
133
+ }
134
+
135
+ evaluateWhen('dockOpen && vite.mode == development', ctx) // true
136
+ evaluateWhen('clientType == standalone', ctx) // false
137
+
138
+ getContextValue('vite.mode', ctx) // 'development'
139
+ getContextValue('dockOpen', ctx) // true
140
+ ```
141
+
142
+ ### `evaluateWhen(expression, ctx)`
143
+
144
+ Evaluates a when-clause expression string against a context object. Returns `boolean`.
145
+
146
+ ### `getContextValue(key, ctx)`
147
+
148
+ Resolves a single context key (including namespaced keys) from the context object. Returns `unknown`.
149
+
150
+ ### `WhenContext`
151
+
152
+ ```ts
153
+ interface WhenContext {
154
+ clientType: 'embedded' | 'standalone'
155
+ dockOpen: boolean
156
+ paletteOpen: boolean
157
+ dockSelectedId: string
158
+ [key: string]: unknown // custom plugin variables
159
+ }
160
+ ```