# @salesforce/ui-bundle-template-feature-cms-toolkit

![Status: Beta](https://img.shields.io/badge/status-beta-orange)

Framework-agnostic APIs for reading Salesforce CMS delivery content — by public
URL or `contentKey`, single or bulk — plus CMS image-URL resolution and RichText
decoding.

> 🧪 **Beta.** This feature is in beta. It is usable today, but the API may
> change in a future release, and breaking changes can land in a minor version.
> The public surface is **additive-only** — new capability arrives as new
> optional options, new named exports, or new error subclasses, never as a
> changed signature. Pin the package version and review the
> [CHANGELOG](./CHANGELOG.md) before upgrading.

> 🧩 **Pure TypeScript — no UI framework.** This package ships `.ts` source only:
> no React/Angular/Vue, no JSX, no routes or pages. You import the functions and
> call them from your own framework code; renderers live in your app.

## Installation

```bash
npm install @salesforce/ui-bundle-template-feature-cms-toolkit
```

Then import what you need from the package entry point:

```ts
import { getCmsContentByKey } from "@salesforce/ui-bundle-template-feature-cms-toolkit";
```

Alternatively, install it through the feature CLI, which copies the `cmsToolkit`
source into your UI Bundle (then import from `./features/cmsToolkit`):

```bash
npx @salesforce/ui-bundle-features install cms-toolkit --ui-bundle-dir <path/to/ui-bundle>
```

## Quick start

```ts
import {
  getCmsContentByUrl,
  getCmsContentByKey,
  resolveCmsImageUrl,
  decodeRichHtmlEntities,
} from "@salesforce/ui-bundle-template-feature-cms-toolkit";

// Public CDN read — unauthenticated.
const news = await getCmsContentByUrl("https://<cdn>/.../news-article");

// Authenticated read by contentKey (via the Connect API). Throws on miss.
const article = await getCmsContentByKey("MC...", { channelId: "0ap..." });

// Resolve a CMS image field to a loadable URL, and decode RichText for render.
const src = resolveCmsImageUrl(article.heroImage);
const html = decodeRichHtmlEntities(article.body);
```

## Public API

Import everything from the package entry point — never deep-import internal
modules.

```ts
// Reads
getCmsContentByUrl(url, options?)            // public URL (unauthenticated CDN)
getCmsContentByKey(key, options?)            // one item by contentKey (throws on miss)
getCmsContentByKeys(keys, options?)          // bulk (best-effort; per-key result/error)

// Utilities
resolveCmsImageUrl(field, options?)          // CMS image field → loadable URL
resolveMediaUrl(url, options?)               // raw media URL string → loadable URL
resolveEffectiveContentKey(key, catalogUrl?) // catalog source→target key remap
getCmsDefaultChannelId(catalogUrl?)          // catalog default channelId (fail-open)
getCmsInstanceOrigin()                       // instance origin for media prefixing
decodeRichHtmlEntities(encoded)              // decode RichText before sanitize + inject

// Errors (stable for instanceof) and types
CmsDeliveryError, CmsDeliveryNotFoundError, ConnectApiError, CmsNotFoundError
CmsContentBody, CmsReadOptions, CmsBulkResult, CmsContentCatalog, CmsImageField, CmsImageOptions
```

## Requirements

- `@salesforce/platform-sdk` — backs the authenticated by-`contentKey` transport
  (`createDataSDK().fetch`). Public-URL reads are unauthenticated and need no
  session.
- `@salesforce/ui-bundle` — supplied by the base app.
