7f20f36d0a
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.
33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
import { NonRetryableError } from '$shared/api/queryClient';
|
|
|
|
/**
|
|
* Thrown when the network request to the proxy API fails.
|
|
* Wraps the underlying fetch error (timeout, DNS failure, connection refused, etc.).
|
|
*/
|
|
export class FontNetworkError extends Error {
|
|
readonly name = 'FontNetworkError';
|
|
|
|
constructor(public readonly cause?: unknown) {
|
|
super('Failed to fetch fonts from proxy API');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Thrown when the proxy API returns a response with an unexpected shape.
|
|
* Extends NonRetryableError because schema mismatches are not transient —
|
|
* retrying will produce the same failure and only delay surfacing the bug.
|
|
*
|
|
* @property field - The name of the field that failed validation (e.g. `'response'`, `'response.fonts'`).
|
|
* @property received - The actual value received at that field, for debugging.
|
|
*/
|
|
export class FontResponseError extends NonRetryableError {
|
|
readonly name = 'FontResponseError';
|
|
|
|
constructor(
|
|
public readonly field: string,
|
|
public readonly received: unknown,
|
|
) {
|
|
super(`Invalid proxy API response: ${field}`);
|
|
}
|
|
}
|