You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
store: fixes and improvements for the NgRx inspector #347
Fixes and improvements from a code audit of the ngrx inspector, done in October 2026. Roadmap work lives in #340, #341, #342 and #343. Items marked (to confirm) were not reproduced; check them before fixing.
Problems
Medium
Long diffs are cut off silently: each entry keeps at most 50 diff rows (MAX_DIFF), and nothing marks the entry as truncated. The panel shows "50 changes" and the rows as if complete, and agents get the same partial diff. Add a diffTruncated count to NgrxLogEntry, and show "N more changes not shown" in the panel and in agent text (packages/devtools/src/ngrx-collector.ts:104, :173-190, :746; packages/devtools/src/ngrx-shared.ts:77; app/src/pages/store-inspector.ts:391, :604-620).
Store DevTools history actions are missing:NgrxRequest only has restore, latest, dispatch and dispatch-again. Skip or toggle an action, commit, reset, sweep, pause recording and lock changes are not offered, though Store DevTools already has them (toggleAction, commit, reset, sweep, pauseRecording, lockChanges). Wire them as NgrxRequest types behind the ngrx action gate and list them in ACTION_TOOLS (packages/devtools/src/ngrx-shared.ts:137-141).
No call site for any entry: an entry only records origin (dispatch, effect or reactive). There is no stack capture in the dispatch or method wrappers, so you cannot see where an action or patchState came from. Add an opt-in ngrx.trace option that captures new Error().stack, trims devtools and framework frames, redacts it and shows it as a file link (packages/devtools/src/ngrx-collector.ts:836-880).
Low
Classic state is serialized twice:logClassic serializes the whole classic state on every action, then report() serializes it again on the next push, and the overlay compares the JSON.stringify body. same() also compares nested objects with JSON.stringify. Cache the serialized state while lastRaw is unchanged by reference, and drop the string compare in same() (packages/devtools/src/ngrx-collector.ts:745, :1164; packages/devtools/src/ngrx-shared.ts:300-304; packages/devtools/src/ngrx-overlay.ts:67).
Report entries are not shape-checked:isNgrxReport checks that stores and log are arrays, but not their items, classic or the size. A null log entry throws in mergeNgrxReport (entry.seq), and a large classic or store blob is kept as is. Validate items with valibot like rpc/get-ngrx-store.ts does, drop bad entries, and cap the size per page (packages/devtools/src/rpc/ngrx-tools.ts:32-41, :86-128; packages/devtools/src/devframe.ts:1550).
The collector patches store objects: it wraps store methods in Proxies, replaces set and update on state signals, and patches Store.dispatch, next and Dispatcher.dispatch. This adds overhead on every call and may clash with withDevtools from @angular-architects/ngrx-toolkit. Use watchState alone when it is registered, document the interaction, and consider a record toggle that unwraps everything (packages/devtools/src/ngrx-collector.ts:446-512, :672-715, :836-880) (to confirm).
Improvements
A slider over the change log to scrub through past states (app/src/pages/store-inspector.ts).
Show store state as a collapsible tree with search and "copy path" instead of a <pre> block, and highlight the keys the selected entry changed (app/src/pages/store-inspector.ts:259).
An agent tool that explains why a state changed, following causedByEvent, origin and the stack from event to reducer to diff (packages/devtools/src/rpc/ngrx-live-tools.ts, packages/devtools/src/config.ts).
An action frequency and duration view per action type, flagging effects that dispatch in a loop (packages/devtools/src/ngrx-collector.ts, app/src/pages/store-inspector.ts).
Already tracked elsewhere
Full state at a past entry with State, Diff and Action tabs, session export and import, and generated tests: phase 4 of 4: deeper diagnosis #343.
Context
Fixes and improvements from a code audit of the ngrx inspector, done in October 2026. Roadmap work lives in #340, #341, #342 and #343. Items marked (to confirm) were not reproduced; check them before fixing.
Problems
Medium
MAX_DIFF), and nothing marks the entry as truncated. The panel shows "50 changes" and the rows as if complete, and agents get the same partial diff. Add adiffTruncatedcount toNgrxLogEntry, and show "N more changes not shown" in the panel and in agent text (packages/devtools/src/ngrx-collector.ts:104,:173-190,:746;packages/devtools/src/ngrx-shared.ts:77;app/src/pages/store-inspector.ts:391,:604-620).NgrxRequestonly hasrestore,latest,dispatchanddispatch-again. Skip or toggle an action, commit, reset, sweep, pause recording and lock changes are not offered, though Store DevTools already has them (toggleAction,commit,reset,sweep,pauseRecording,lockChanges). Wire them asNgrxRequesttypes behind the ngrx action gate and list them inACTION_TOOLS(packages/devtools/src/ngrx-shared.ts:137-141).origin(dispatch, effect or reactive). There is no stack capture in the dispatch or method wrappers, so you cannot see where an action orpatchStatecame from. Add an opt-inngrx.traceoption that capturesnew Error().stack, trims devtools and framework frames, redacts it and shows it as a file link (packages/devtools/src/ngrx-collector.ts:836-880).Low
logClassicserializes the whole classic state on every action, thenreport()serializes it again on the next push, and the overlay compares theJSON.stringifybody.same()also compares nested objects withJSON.stringify. Cache the serialized state whilelastRawis unchanged by reference, and drop the string compare insame()(packages/devtools/src/ngrx-collector.ts:745,:1164;packages/devtools/src/ngrx-shared.ts:300-304;packages/devtools/src/ngrx-overlay.ts:67).isNgrxReportchecks thatstoresandlogare arrays, but not their items,classicor the size. Anulllog entry throws inmergeNgrxReport(entry.seq), and a largeclassicor store blob is kept as is. Validate items with valibot likerpc/get-ngrx-store.tsdoes, drop bad entries, and cap the size per page (packages/devtools/src/rpc/ngrx-tools.ts:32-41,:86-128;packages/devtools/src/devframe.ts:1550).setandupdateon state signals, and patchesStore.dispatch,nextandDispatcher.dispatch. This adds overhead on every call and may clash withwithDevtoolsfrom@angular-architects/ngrx-toolkit. UsewatchStatealone when it is registered, document the interaction, and consider a record toggle that unwraps everything (packages/devtools/src/ngrx-collector.ts:446-512,:672-715,:836-880) (to confirm).Improvements
app/src/pages/store-inspector.ts).<pre>block, and highlight the keys the selected entry changed (app/src/pages/store-inspector.ts:259).causedByEvent,originand the stack from event to reducer to diff (packages/devtools/src/rpc/ngrx-live-tools.ts,packages/devtools/src/config.ts).packages/devtools/src/ngrx-collector.ts,app/src/pages/store-inspector.ts).Already tracked elsewhere
pagereaching every tab (devframe.ts:1582,ngrx-overlay.ts:107): phase 1 of 4: safe by default and wired into your workflow #340.Generated by Claude Code