Skip to content

fix: resolve high-severity audit issues in core query and React bindings#3

Merged
ConsoleTVs merged 1 commit intomainfrom
fix/audit-high-severity-issues
Apr 12, 2026
Merged

fix: resolve high-severity audit issues in core query and React bindings#3
ConsoleTVs merged 1 commit intomainfrom
fix/audit-high-severity-issues

Conversation

@ConsoleTVs
Copy link
Copy Markdown
Member

Summary

Resolves all 6 high-severity issues identified during a deep code audit of the core query library and React bindings.

Core Library Fixes

H1: fresh option ignoring configure()

src/query/query.ts:345 — The fresh option in query() was falling back to instanceOptions?.fresh (the original constructor argument) instead of instanceFresh (the runtime-mutable variable). This meant calling configure({ fresh: true }) had no effect on subsequent query() calls. Every other option correctly fell back to its instance* variable.

H2: fresh: true not forcing a new fetch when request is in-flight

src/query/query.ts:417-421 — When fresh: true was passed but a request was already in-flight, refetch() returned the existing pending promise from the resolver cache (deduplication). This defeated the entire purpose of fresh. Fixed by aborting any existing in-flight request before calling refetch().

H3: next() broken for plain object keys

src/query/query.ts:504-511 — The type signature of next() accepted string | { [K in keyof T]: string } (including plain objects), but the implementation only checked Array.isArray(keys). A plain object like { a: '/foo', b: '/bar' } was wrapped in [keys] and cast to string[], producing completely wrong behavior. Fixed by handling all three cases: string, string[], and plain objects. Same fix applies to stream() and sequence() which delegate to next().

React Bindings Fixes

H4: Stale data on key change in useQueryBasic

src/react/hooks/useQueryBasic.ts:95useState(use(promise)) only captured the initial value. When the key prop changed to a different already-cached key, use() returned the new data but useState ignored it (not initial render). The component displayed stale data from the previous key. Fixed by comparing the use()-resolved value with current state and resetting when they differ.

H5: Shadowed generic <T> in useQueryActions.localMutate

src/react/hooks/useQueryActions.ts:93localMutate<T = unknown> declared its own generic T that shadowed the outer hook's T from useQueryActions<T>. This disconnected the mutation function's type parameter from the hook's type, causing the returned mutate function to default to unknown instead of the caller's type. Fixed by removing the inner generic.

Documentation & Dependencies

H6: React Compiler documentation + test coverage

  • Added "React Compiler" section to AGENTS.md documenting build configuration, plugin order, and rules for React code (no manual memoization, immutability, etc.)
  • Added @babel/core as an explicit devDependency (required peer dep of @rolldown/plugin-babel per @vitejs/plugin-react docs)
  • Added test files for useQueryBasic, useQueryActions, and useQueryStatus hooks (previously 0 test coverage)

Tests

  • 12 new tests added (4 core query + 3 useQueryBasic + 3 useQueryActions + 2 useQueryStatus)
  • All 61 tests pass
  • Lint, format check, and build all pass

- Fix fresh option falling back to constructor arg instead of instanceFresh
- Fix fresh:true returning pending dedup promise instead of forcing new fetch
- Fix next()/stream()/sequence() broken for plain object keys
- Fix stale data displayed on key change in useQueryBasic
- Fix shadowed generic <T> in useQueryActions.localMutate
- Document React Compiler setup and rules in AGENTS.md
- Add @babel/core as explicit devDependency (peer dep of @rolldown/plugin-babel)
- Add test coverage for useQueryBasic, useQueryActions, and useQueryStatus hooks
@ConsoleTVs ConsoleTVs marked this pull request as ready for review April 12, 2026 12:14
@ConsoleTVs ConsoleTVs merged commit b25c0c5 into main Apr 12, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant