Vize

Command Router

Headless Command Router; covers VS Code command registry, Ariakit Combobox commands, kbar actions.

Package @vizejs/ui/command
Maturity stable
Own the source vize lib pull command
Requires —
Aliases command registry, command routing, action dispatcher
Covers VS Code command registry, Ariakit Combobox commands, kbar actions

API

createCommandRouter

Create a typed command router with enablement and help metadata. The router owns no DOM and is safe to create during server rendering. Registering an identifier twice throws a conflict diagnostic so palettes, menus, and shortcut layers cannot silently shadow one another. Call CommandRouter.dispose when using this factory outside a Vue effect scope.

function createCommandRouter<Id extends string = string>( options: CommandRouterOptions<Id> = {}, ): CommandRouter<Id>

useCommandRouter

Create a command router disposed with the current Vue effect scope.

function useCommandRouter<Id extends string = string>( options: CommandRouterOptions<Id> = {}, ): CommandRouter<Id>

Behavior

Normative state × input → outcome table for @vizejs/ui/command. Every row is exercised by src/families/foundations/command/command.test.ts or src/families/foundations/command/command-ssr.test.ts; compile-only assertions live in src/families/foundations/command/command.types.test-d.ts.

# State Input Outcome Proven by
C1 registered command execute with its identifier run receives a frozen execution context and the dispatch reports it dispatch test
C2 registered command execute with a payload and source payload and source thread through to the handler and observers dispatch test
C3 unknown identifier execute dispatch reports not-found and no handler or observer runs routing test
C4 disabled command execute while when resolves false dispatch reports disabled and run never fires enablement test
C5 disabled router execute while isDisabled is true every command reads as disabled until the gate clears enablement test
C6 registered identifier second registration of the same id stable conflict diagnostic rejects the duplicate, keeping the original conflict test
C7 released registration re-registration of the freed id registration succeeds and help metadata updates conflict test
C8 any registrations commands read reactive frozen help metadata lists id, title, keywords, and enablement help-metadata test
C9 observer configured dispatch that found its command onDidExecute receives the frozen dispatch after the handler completes observer test
C10 handler throws execute the failure surfaces to the caller and no dispatch is reported failure test
C11 invalid options malformed definition or option values stable runtime diagnostics reject the misuse diagnostics test
C12 active router dispose or Vue scope stop registrations clear and imperative calls become terminal lifecycle test
C13 concurrent SSR requests identical consumers byte-identical markup with no request-global registration state SSR test
C14 SSR followed by hydration dispatch from a hydrated control host identity remains and the command runs without warnings hydration test
C15 DOM, SSR, and Vapor lanes authored consumer compiles every renderer accepts the same router surface renderer gate
C16 root and subpath consumer only command is retained equal CSS-free bundles exclude unrelated component families tree-shaking gate
C17 public TypeScript API unknown identifier or invalid options compile-only assertions reject misuse type declaration test

Accessibility obligation

The router is headless plumbing for palettes, menus, and shortcut layers; it never owns semantics itself. Consumers must reflect enablement onto the controls that trigger a command (disabled or aria-disabled), keep every command reachable through visible focusable controls rather than shortcuts alone, and use the help metadata (title, description, group) as the accessible names of palette and menu items so the spoken and visible labels stay identical.