Controller model
Everything in msw-panel orbits the controller interface exposed by msw-panel.
Controller contract
Section titled “Controller contract”interface MswPanelController { getSnapshot(): MswPanelSnapshot; setAllEnabled(nextEnabled: boolean): void; setEnabled(id: string, nextEnabled: boolean): void; subscribe(listener: () => void): () => void; sync(): void; toggle(id: string): void;}That small surface area is intentional. The React panel uses it directly, and the bridge client emulates the same shape over a transport boundary.
Snapshot model
Section titled “Snapshot model”The controller exposes a derived snapshot rather than leaking internal state. A snapshot includes:
- the active handler count
- the disabled handler count
- one entry per handler with
id,enabled,kind,label,method,path, andused, plus optionaltags,scenarios, andactiveScenario - the registered global
presetsand the currently matchingactivePreset
Because the snapshot is plain data, UI adapters and transports do not need to know anything about MSW internals.
Interactive example
Controller snapshot playground
Toggle handlers, add a runtime handler, and then call sync() to see how the
snapshot catches up.
The snapshot starts aligned with the runtime.
Runtime ownership
Section titled “Runtime ownership”The host application still owns the runtime and the handler list:
const controller = createMswPanelController({ handlers, runtime: worker });That means msw-panel does not replace your mocking setup. It consumes:
- the runtime object that can list and reset handlers
- the handlers your app already defined
Sync behavior
Section titled “Sync behavior”The controller starts from the supplied handler set and can rebuild from the runtime later with sync(). Enabled state and scenario selections are preserved where handler identities still match.
That design is simple and predictable, but it also explains the current limitation: runtime-added handlers do not appear automatically unless the host calls controller.sync().
Scenarios and presets
Section titled “Scenarios and presets”defineScenarios registers a single MSW handler whose resolver dispatches to the currently-active scenario, held in closure-mutable state on the group. setScenario() flips that state and emits a new snapshot. It does not call resetHandlers, so the handler keeps matching and the swap takes effect on the next request. A definePreset simply records a set of scenario selections; applyPreset() applies them all and the snapshot reports which preset (if any) the current selections match. Because all of this lives next to the handlers, scenario and preset commands flow over the bridge to the controller the same way enable/disable does.