Skip to content

Migration 0.2 → 0.3

v0.3.0 adds capabilities, search filters, and public API cleanup on top of the multi-provider work shipped in v0.2.0. Upgrading is optional for existing Pexels-only apps — search and pagination behave the same when you do not pass filters.

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

Summary of changes

Areav0.2.0v0.3.0
CapabilitiesNot availableclient.capabilities, getCapabilities(), useMediaCapabilities()
Search filtersNot availablephotoFilters / videoFilters on SearchParams and hooks
Abort detectionManual error.name === "AbortError"isAbortError(error) exported from @media-sdk/core
Pexels wire typesPublic exportsMarked @deprecated — removal planned for v1.0
HTTP error messagesPexels-branded textProvider-neutral (HTTP request failed: …)
Unsupported filtersN/AThrows MediaError with code: "UNSUPPORTED_FILTER"

Capabilities (optional adoption)

v0.3.0 introduces MediaCapabilities so UIs can adapt to the active provider without branching on provider name strings.

Core

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

const pexelsCaps = getCapabilities(pexelsClient);
// pexelsCaps.operations.curatedPhotos === true

const pixabayCaps = getCapabilities(pixabayClient);
// pixabayCaps.operations.curatedPhotos === false

Custom clients without a capabilities property receive an all-false fallback from getCapabilities.

React

tsx
import { useMediaCapabilities } from "@media-sdk/react";

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

  return (
    <>
      {caps.photoFilters.orientation && (
        <OrientationSelect />
      )}
      {caps.photoFilters.size && (
        <SizeSelect />
      )}
    </>
  );
}

Migration pattern

Replace provider-string conditionals:

tsx
// ❌ v0.2 pattern — do not use in new code
if (provider === "pexels") {
  showCuratedTab();
}

// ✅ v0.3 pattern
const caps = useMediaCapabilities();
if (caps.operations.curatedPhotos) {
  showCuratedTab();
}

See Capabilities and the provider comparison matrix.

Filters (optional adoption)

v0.3.0 adds normalized filter types on SearchParams:

ts
interface SearchParams {
  query: string;
  page?: number;
  perPage?: number;
  signal?: AbortSignal;
  photoFilters?: PhotoSearchFilters;  // new in 0.3.0
  videoFilters?: VideoSearchFilters;  // new in 0.3.0
}

Core

ts
const results = await client.searchPhotos({
  query: "nature",
  photoFilters: {
    orientation: "landscape",
    size: "large",
    color: "blue",
  },
});

React hooks

useMediaSearch and useMediaVideos forward filters unchanged:

tsx
const { data } = useMediaSearch({
  query: "nature",
  photoFilters: { orientation: "landscape" },
});

const { data: videos } = useMediaVideos({
  query: "ocean",
  videoFilters: { orientation: "landscape", size: "medium" },
});

Hooks do not strip unsupported filters. Gate filter UI with useMediaCapabilities().photoFilters / .videoFilters before passing values.

UNSUPPORTED_FILTER handling

Unsupported filters throw MediaError with code: "UNSUPPORTED_FILTER" — they are never silently ignored:

tsx
import { MediaError } from "@media-sdk/core";

try {
  await client.searchPhotos({
    query: "nature",
    photoFilters: { size: "large" }, // unsupported on Pixabay photos
  });
} catch (error) {
  if (
    error instanceof MediaError &&
    error.code === "UNSUPPORTED_FILTER"
  ) {
    // hide or disable the size filter for this provider
  }
}

See Filters for the full provider mapping table.

isAbortError

v0.3.0 exports isAbortError from @media-sdk/core as the canonical abort check:

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

if (isAbortError(error)) {
  // request was cancelled
}

Replace manual checks:

ts
// ❌ v0.2 pattern
if (error instanceof Error && error.name === "AbortError") { }

// ✅ v0.3 pattern
import { isAbortError } from "@media-sdk/core";
if (isAbortError(error)) { }

React hooks swallow abort errors in UI state — error stays null when a request is cancelled. See Cancellation.

Deprecated Pexels wire types

The following types are marked @deprecated in v0.3.0 and will be removed in v1.0. Prefer normalized types:

Deprecated typeUse instead
PexelsPhotoSearchResponsePaginatedResponse<Photo>
PexelsVideoVideo
PexelsVideoFileVideoFile (on Video.video_files)
PexelsVideoUserVideo.user fields
PexelsVideoSearchResponsePaginatedResponse<Video>
ts
// ❌ Deprecated
import type { PexelsPhotoSearchResponse } from "@media-sdk/core";

// ✅ Preferred
import type { Photo, PaginatedResponse } from "@media-sdk/core";

If you were importing Pexels wire types for custom HTTP handling, switch to the normalized Photo, Video, and PaginatedResponse<T> types returned by MediaClient methods.

Neutral HTTP error messages

FetchHttpClient no longer throws Pexels-branded error messages. HTTP failures use provider-neutral text:

HTTP request failed: Not Found

Branch on error.code and error.status, not error.message:

tsx
import { MediaError } from "@media-sdk/core";

if (error instanceof MediaError) {
  if (error.code === "UNSUPPORTED_CAPABILITY") {
    // method not available on this provider
  } else if (error.code === "UNSUPPORTED_FILTER") {
    // filter not supported
  } else if (error.code === "INVALID_FILTER_VALUE") {
    // invalid filter value
  } else {
    console.error(error.status, error.message);
  }
}

See Errors.

Error codes (new in 0.3.0)

CodeWhen
UNSUPPORTED_CAPABILITYClient method not available (e.g. getCuratedPhotos on Pixabay)
UNSUPPORTED_FILTERFilter field not supported by the active provider
INVALID_FILTER_VALUEFilter value not accepted (e.g. unsupported color)

UNSUPPORTED_CAPABILITY existed in v0.2.0 for Pixabay curated photos. v0.3.0 adds filter-related codes.

What did not change

  • MediaProvider and useMediaClient still accept any MediaClient (since v0.2.0)
  • useMediaSearch / useMediaVideos hook contract (data, loading, error, pagination) is unchanged
  • @media-sdk/ui-react components remain provider-neutral with no API changes
  • Normalized Photo, Video, and PaginatedResponse types are unchanged
  1. Bump all @media-sdk/* packages to ^0.3.0
  2. Replace error.name === "AbortError" with isAbortError(error) if you handle aborts manually
  3. Replace Pexels wire type imports with normalized types
  4. Optionally adopt useMediaCapabilities() for multi-provider UIs
  5. Optionally add photoFilters / videoFilters with capability-gated UI
  6. Run your test suite — HTTP error message assertions may need updating

Further reading