queryClient.ts constructed the TanStack client at module eval but was not
in the sideEffects allowlist, so Rollup treated the module as pure — safe
only while a value-importer keeps it alive (D-3).
- replace the eager `queryClient` singleton with a memoized getQueryClient()
factory; construction is deferred to first call
- the module is now genuinely side-effect-free, so no sideEffects exception
is needed and construction can never be legally tree-shaken away
- route all consumers through getQueryClient() (QueryProvider as first
caller; stores via class fields/observers; tests via a local alias; the
fontCatalogStore spec mock now overrides getQueryClient)
Extract NonRetryableError into its own tanstack-free module and drop the
./api re-export from the Font slice barrel. Importing $entities/Font no
longer transitively loads @tanstack/query-core or constructs the QueryClient
singleton via the ./api and ./lib (errors) chains — light consumers (domain,
types, consts) and unit specs stop paying for TanStack.
Note: ./ui still pulls the stores; addressed separately.
The proxy returned `{fonts: null, total: 0}` for empty results, which
fetchProxyFonts surfaced as a generic Error. fontCatalogStore wrapped it
as FontNetworkError, and TanStack retried 3× with exponential backoff —
pinning the loading skeleton for ~7s before settling on an empty list.
Schema mismatches are deterministic; retrying only delays surfacing the
contract violation.
- shared/api/queryClient: introduce NonRetryableError marker class.
The default retry handler short-circuits when it sees this so any
store using the shared client gets fail-fast behavior for free.
- entities/Font/lib/errors: FontResponseError extends NonRetryableError.
- entities/Font/api/proxy/proxyFonts: throw FontResponseError (was a
bare Error). Document that ProxyFontsResponse.fonts is always an array.
- entities/Font/.../fontCatalogStore.fetchPage: preserve a
FontResponseError raised lower in the stack instead of re-wrapping
it as FontNetworkError.
- features/FilterAndSortFonts/api/filters: throw NonRetryableError on
invalid filters payloads and document the array-never-null contract.