Skip to content

Capabilities

Capabilities describe what a MediaClient supports: which operations exist and which search filters are valid. Use capabilities to build provider-agnostic UIs that adapt when the active client changes.

Installation

bash
pnpm add @media-sdk/core@^0.3.0

For React apps, also install @media-sdk/react@^0.3.0 to use useMediaCapabilities.

MediaCapabilities type

ts
interface MediaCapabilities {
  readonly operations: MediaOperationCapabilities;
  readonly photoFilters: MediaFilterCapabilities;
  readonly videoFilters: MediaFilterCapabilities;
}

interface MediaOperationCapabilities {
  readonly searchPhotos: boolean;
  readonly searchVideos: boolean;
  readonly getPhoto: boolean;
  readonly getVideo: boolean;
  readonly curatedPhotos: boolean;
  readonly trackView: boolean;
  readonly trackDownload: boolean;
}

interface MediaFilterCapabilities {
  readonly orientation: boolean;
  readonly size: boolean;
  readonly color: boolean;
  readonly category: boolean;
  readonly minWidth: boolean;
  readonly minHeight: boolean;
  readonly editorsChoice: boolean;
  readonly locale: boolean;
}

SDK clients set these flags to match their provider. See the provider comparison matrix.

client.capabilities

PexelsMediaClient and PixabayMediaClient expose a readonly capabilities property:

ts
import { PexelsMediaClient } from "@media-sdk/core";

const client = new PexelsMediaClient(auth);

console.log(client.capabilities.operations.curatedPhotos); // true
console.log(client.capabilities.photoFilters.size);        // true

Custom implementations may omit capabilities. Always prefer getCapabilities for portable code.

getCapabilities(client)

getCapabilities returns client.capabilities when present, or a conservative all-false fallback (DEFAULT_CAPABILITIES) when absent:

ts
import {
  ApiKeyProvider,
  getCapabilities,
  PexelsMediaClient,
  PixabayMediaClient,
} from "@media-sdk/core";

const pexels = new PexelsMediaClient(
  new ApiKeyProvider(process.env.PEXELS_API_KEY!),
);
const pixabay = new PixabayMediaClient(
  new ApiKeyProvider(process.env.PIXABAY_API_KEY!),
);

const pexelsCaps = getCapabilities(pexels);
const pixabayCaps = getCapabilities(pixabay);

if (pexelsCaps.operations.curatedPhotos) {
  await pexels.getCuratedPhotos({ page: 1, perPage: 20 });
}

// pixabayCaps.operations.curatedPhotos === false

Discover + throw semantics

Capabilities serve two roles:

  1. Discover — UI reads flags to show or hide controls before calling the client.
  2. Throw — Calling an unsupported operation or filter still throws MediaError even if you skip the guard. Capabilities are advisory for UX; the client enforces the contract.
ts
// Guarded — good UX, no error
if (getCapabilities(client).operations.curatedPhotos) {
  await client.getCuratedPhotos({ page: 1 });
}

// Unguarded on Pixabay — throws UNSUPPORTED_CAPABILITY
await pixabay.getCuratedPhotos({ page: 1 });

UI gating example (core)

Build filter objects from capability flags before searching:

ts
import {
  getCapabilities,
  type MediaClient,
  type PhotoSearchFilters,
} from "@media-sdk/core";

async function searchLandscape(
  client: MediaClient,
  query: string,
) {
  const caps = getCapabilities(client);
  const filters: PhotoSearchFilters = {};

  if (caps.photoFilters.orientation) {
    filters.orientation = "landscape";
  }
  if (caps.photoFilters.category) {
    filters.category = "nature";
  }
  if (caps.photoFilters.size) {
    filters.size = "large";
  }

  return client.searchPhotos({
    query,
    page: 1,
    perPage: 20,
    photoFilters: filters,
  });
}

Never branch on provider === "pexels". Branch on caps.photoFilters.size, caps.operations.curatedPhotos, etc.

useMediaCapabilities (React)

In React apps, wrap your tree with MediaProvider and read capabilities from context:

tsx
import { MediaProvider } from "@media-sdk/react";
import { PexelsMediaClient, ApiKeyProvider } from "@media-sdk/core";

const client = new PexelsMediaClient(
  new ApiKeyProvider(import.meta.env.VITE_PEXELS_API_KEY),
);

function App() {
  return (
    <MediaProvider client={client}>
      <SearchUI />
    </MediaProvider>
  );
}
tsx
import { useMediaCapabilities } from "@media-sdk/react";

function SearchUI() {
  const caps = useMediaCapabilities();

  return (
    <div>
      {caps.operations.curatedPhotos && (
        <button type="button">Curated</button>
      )}
      {caps.photoFilters.orientation && (
        <OrientationSelect />
      )}
      {caps.photoFilters.size && <SizeSelect />}
      {caps.photoFilters.category && <CategorySelect />}
    </div>
  );
}

useMediaCapabilities is a thin wrapper around getCapabilities(useMediaClient()). When MediaProvider receives a new client prop, the hook re-renders with updated flags.

See the React hooks guide for MediaProvider, useMediaSearch, and related hooks.

Capability matrix reference

Filter / operationPexels photosPexels videosPixabay photosPixabay videos
searchPhotos / searchVideos
getPhoto / getVideo
curatedPhotos
trackView / trackDownload
orientation
size
color
category
minWidth / minHeight
editorsChoice
locale