Files
siftlode/frontend/src/lib/api.ts
T
peter 56a2ecdec3 feat(plex): shareable Plex-browse state in the URL — scope+filters+sort+show (S4)
Mirror the Plex-browse content state into the address bar so a browse view is
bookmarkable/shareable, the Plex analogue of the feed's urlState. Keys are
NAMESPACED (pscope/psort/pshow/pf) rather than reusing the feed's bare
scope/sort/show: FeedFiltersProvider actively strips its own KEYS from the URL
whenever off the feed page, so a shared key would be deleted out from under the
Plex page. The namespaced keys are Plex-unique (like ?v=/?pl), so no other
provider ever reads or clears them.

- New lib/plexUrlState.ts: plexParamUpdates / plexParamsToState / hasPlexParams.
  The pf filter blob reuses the SAME appendPlexFilters wire serializer (new
  public plexFiltersToParams + inverse parsePlexFilters, kept next to each other
  so a new wire key can't be added on one side only).
- PlexProvider: URL-seed wins over localStorage at mount; the account-pin
  rehydrate persists the seed instead of clobbering it (mirrors feed's
  initialHadUrlFilters); useUrlMirror mirrors/clears the 4 keys, gated on
  page===plex. q/field stay out of the shareable contract.
- NavigationProvider: a page switch now also nulls the 4 plex keys.

Tests: 8 new round-trip cases in plexUrlState.dom.test.ts (FE vitest 483→491).
2026-08-27 03:14:54 +02:00

91 lines
2.7 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 {
getActiveAccount,
HttpError,
setActiveAccount,
clearActiveAccount,
setUnauthorizedHandler,
} from "./api/core";
// Re-export the shared HTTP machinery so consumers keep importing these from "./api" unchanged.
export {
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";
import { setupApi } from "./api/setup";
export type * from "./api/setup";
import { feedApi } from "./api/feed";
export type * from "./api/feed";
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,
...channelsApi,
...syncApi,
...playlistsApi,
...tagsApi,
...notificationsApi,
...savedViewsApi,
...quotaApi,
...adminApi,
...plexApi,
...messagingApi,
...downloadsApi,
};