Files
siftlode/frontend/src/lib/api.ts
T
peter 1cfe6a7f59 fix(api): a gone row and a refused playlist action are said in the reader's language, and a failure is reported once
Deep-review round 3 of bug hunt 2026-09.

- get_or_404 / owned_or_404 answer a structured {code: "not_found", reason: <what>}
  (errors.notFound.* in HU+EN, generic fallback). The structured-404 fix of round 2 had gone into the
  ad-hoc `_own_playlist` (CLAUDE.md's "Not" pattern) while the shared helpers stayed string-only, so
  views, tags, pins, Plex playlists, invites and users still 404'd in English. `_own_playlist` now
  goes through owned_or_404; admin's hand-rolled user lookups use get_or_404.
- A move into a list that is gone names the TARGET (reason "move_target") — "this playlist doesn't
  exist any more" was read as the list on screen, which still exists.
- Every refusal in the playlists router is a {code: "playlist", reason} (playlists.errors.* HU+EN)
  instead of a bare English string shown verbatim in the Hungarian UI.
- `req` / `uploadReq` mark the errors they already put on screen (the error dialog, the connection
  notice, the 401 sign-out), and notifyActionError skips those. The watched toggles, the saved views
  and a playlist delete toasted a fault the dialog was already showing; Playlists' two hand-written
  status filters now go through the same check.
2026-09-11 18:05:19 +02:00

98 lines
3.0 KiB
TypeScript

// The API façade. This file owns NO endpoint logic and NO types of its own — every domain lives in
// its own api/<domain>.ts module (types + method slice together). This barrel only:
// 1. re-exports the shared HTTP machinery from api/core,
// 2. re-exports each domain's TYPES (`export type *`) so consumers import them from "./api"
// unchanged,
// 3. spreads each domain's method slice into the single `api` object consumers call.
// A new endpoint therefore has nowhere to land except a domain module — the interleave that
// motivated R7.5 cannot re-grow here. (An automated guard for that invariant lands in S3.)
import {
alreadyReported,
getActiveAccount,
HttpError,
setActiveAccount,
clearActiveAccount,
setUnauthorizedHandler,
} from "./api/core";
// Re-export the shared HTTP machinery so consumers keep importing these from "./api" unchanged.
export {
alreadyReported,
HttpError,
getActiveAccount,
setActiveAccount,
clearActiveAccount,
setUnauthorizedHandler,
};
import { accountApi } from "./api/account";
export type * from "./api/account";
import { authApi } from "./api/auth";
export type * from "./api/auth";
export { loginBlocked, deadResetLink } from "./api/auth";
import { setupApi } from "./api/setup";
export type * from "./api/setup";
import { feedApi } from "./api/feed";
export type * from "./api/feed";
import { discoverApi } from "./api/discover";
export type * from "./api/discover";
export { DISCOVER_BUDGETS, discoverCardKey } from "./api/discover";
export type * from "./api/tagModes";
export {
DEFAULT_TAG_MODES,
TAG_CATEGORIES,
NO_TAG_SENTINEL,
coerceTagModes,
coerceUntagged,
} from "./api/tagModes";
import { channelsApi } from "./api/channels";
export type * from "./api/channels";
import { syncApi } from "./api/sync";
export type * from "./api/sync";
import { playlistsApi } from "./api/playlists";
export type * from "./api/playlists";
import { tagsApi } from "./api/tags";
export type * from "./api/tags";
import { notificationsApi } from "./api/notifications";
export type * from "./api/notifications";
import { savedViewsApi } from "./api/savedViews";
export type * from "./api/savedViews";
import { quotaApi } from "./api/quota";
export type * from "./api/quota";
import { adminApi } from "./api/admin";
export type * from "./api/admin";
import { plexApi } from "./api/plex";
export type * from "./api/plex";
export {
EMPTY_PLEX_FILTERS,
plexFilterCount,
coercePlexFilters,
plexFiltersSignature,
plexFiltersToParams,
parsePlexFilters,
isIntrinsicReadOnly,
} from "./api/plex";
import { messagingApi } from "./api/messaging";
export type * from "./api/messaging";
import { downloadsApi } from "./api/downloads";
export type * from "./api/downloads";
export const api = {
...accountApi,
...authApi,
...setupApi,
...feedApi,
...discoverApi,
...channelsApi,
...syncApi,
...playlistsApi,
...tagsApi,
...notificationsApi,
...savedViewsApi,
...quotaApi,
...adminApi,
...plexApi,
...messagingApi,
...downloadsApi,
};