refactor(errors): defer mutation errors to global handler
Now that MutationCache toasts via toUserMessage by default, the per-hook onError duplicates drop away. Also normalizes inline query-error UI and surfaces a previously-silent failure. Mutations — removed redundant onError toasts: - network-selector: useAcceptInvitation, createNetwork (inline) - network-settings: useInviteMembers, useRevokeInvitation, useRemoveMember - network-billing: useCreateCheckoutSession, useCreatePortalSession (onSuccess toasts stay — they carry domain context like network name) Queries — consistent inline error UX via toUserMessage: - network-selector: failed-to-load state gets a "Try again" button - network-billing: "Couldn't load billing" includes friendly reason - network-settings: useNetworkInvitations failure now surfaces a hint (previously rendered as "0 pending" — silently wrong) Trimmed noisy JSDoc from PR 1 files (errors.ts, query-client.ts, app-error-boundary.tsx, error-fallback.tsx, ipc-utils.ts).
This commit is contained in:
+4
-21
@@ -1,9 +1,6 @@
|
||||
import { z } from "zod";
|
||||
import { appEnv } from "@/config/env";
|
||||
|
||||
/**
|
||||
* Thrown by the API client for any non-2xx response.
|
||||
*/
|
||||
export class ApiError extends Error {
|
||||
constructor(
|
||||
public status: number,
|
||||
@@ -16,9 +13,8 @@ export class ApiError extends Error {
|
||||
|
||||
/**
|
||||
* Thrown when a free-plan network attempts to create a non-container particle
|
||||
* after hitting its daily message limit. Callers should surface an upgrade
|
||||
* prompt; compose UI should also disable triggers proactively via
|
||||
* `useNetworkUsage` rather than relying on this throw.
|
||||
* after hitting its daily message limit. Compose UI also disables triggers
|
||||
* proactively via `useNetworkUsage` — this throw is a last-line defense.
|
||||
*/
|
||||
export class QuotaExceededError extends Error {
|
||||
constructor(public readonly networkId: string) {
|
||||
@@ -33,11 +29,6 @@ function normalizeMessage(message: string): string {
|
||||
return message.replace(IPC_PREFIX, "").replace(/^Error:\s*/, "").trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps any thrown value to a short, user-facing string. Used by the global
|
||||
* MutationCache toast handler, the error-boundary fallback, and any call site
|
||||
* that wants to surface an error in the UI.
|
||||
*/
|
||||
export function toUserMessage(err: unknown): string {
|
||||
if (err instanceof ApiError) {
|
||||
if (err.status === 401) return "Please sign in again.";
|
||||
@@ -69,11 +60,7 @@ export function toUserMessage(err: unknown): string {
|
||||
|
||||
type ErrorContext = Record<string, unknown>;
|
||||
|
||||
/**
|
||||
* For expected-but-worth-recording failures (silent-catch sites). In dev,
|
||||
* prints to console. In prod today this is a no-op; PR 4 wires this up to
|
||||
* Sentry breadcrumbs without touching call sites.
|
||||
*/
|
||||
/** Expected-but-recordable failures. Dev logs; prod is currently a no-op. */
|
||||
export function logError(err: unknown, context?: ErrorContext): void {
|
||||
if (appEnv === "dev") {
|
||||
// eslint-disable-next-line no-console
|
||||
@@ -81,11 +68,7 @@ export function logError(err: unknown, context?: ErrorContext): void {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For unexpected failures the user may not have seen (render crashes, query
|
||||
* errors, background mutations). Always surfaces somewhere. PR 4 wires this
|
||||
* up to `Sentry.captureException`.
|
||||
*/
|
||||
/** Unexpected failures the user may not see. Always surfaces somewhere. */
|
||||
export function reportError(err: unknown, context?: ErrorContext): void {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("[error]", err, context ?? {});
|
||||
|
||||
Reference in New Issue
Block a user