@vigilkids/cms-client
v0.3.5
Published
Framework-agnostic TypeScript client for OnEx CMS Public API
Readme
@vigilkids/cms-client
Framework-agnostic TypeScript client for the OneX CMS Public API. It provides a typed fetch-based client for published CMS content, sitemap data, redirects, comments, authors, series, and server-side webhook signature verification.
Install
pnpm add @vigilkids/cms-clientConfiguration
The baseUrl must point at the CMS Public API root that serves /articles, /search, /sitemap, and the other delivery endpoints.
import { createCmsClient } from '@vigilkids/cms-client'
export const cms = createCmsClient({
baseUrl: 'https://api.example.com/api/v1/cms',
productCode: 'example-product',
defaultLocale: 'en',
timeout: 10_000,
})| Option | Required | Description |
|--------|----------|-------------|
| baseUrl | Yes | CMS Public API base URL. |
| productCode | No | Adds X-Product-Code to each request. |
| defaultLocale | No | Locale automatically added to GET requests when no locale is provided. Defaults to en. |
| previewToken | No | Adds X-Preview-Token to each request. |
| fetch | No | Custom fetch-compatible implementation. Defaults to globalThis.fetch. |
| timeout | No | Request timeout in milliseconds. Defaults to 10000. |
| headers | No | Additional request headers merged into each request. |
Articles
Use getArticles, getArticle, and searchArticles for published article delivery.
import { createCmsClient } from '@vigilkids/cms-client'
const cms = createCmsClient({
baseUrl: 'https://api.example.com/api/v1/cms',
defaultLocale: 'en',
})
export async function loadArticles(): Promise<void> {
const articlePage = await cms.getArticles({
page: 1,
page_size: 10,
sort_by: 'last_published_at',
sort_order: 'desc',
})
const article = await cms.getArticle('getting-started', 'en')
const searchPage = await cms.searchArticles({
q: 'privacy',
locale: 'en',
page: 1,
page_size: 5,
})
console.log(articlePage.pagination.total, article.title, searchPage.data.length)
}Related article and taxonomy helpers are available when the consuming app needs more content context.
import { createCmsClient } from '@vigilkids/cms-client'
const cms = createCmsClient({
baseUrl: 'https://api.example.com/api/v1/cms',
defaultLocale: 'en',
})
export async function loadArticleContext(slug: string): Promise<void> {
const related = await cms.getRelatedArticles(slug, { limit: 3, locale: 'en' })
const categories = await cms.getCategories()
console.log(related.map(article => article.slug), categories.length)
}Sitemap
Use getSitemap to retrieve CMS-managed sitemap entries, including optional route parameters, hreflang entries, and image metadata.
import type { SitemapEntry } from '@vigilkids/cms-client'
import { createCmsClient } from '@vigilkids/cms-client'
const cms = createCmsClient({
baseUrl: 'https://api.example.com/api/v1/cms',
defaultLocale: 'en',
})
export async function loadSitemap(): Promise<SitemapEntry[]> {
const entries = await cms.getSitemap('en')
return entries.filter(entry => entry.loc.startsWith('https://'))
}Webhook Verification
Import webhook helpers from the webhook entry point. Verification uses HMAC-SHA256 and expects a signature formatted as sha256=<hex>.
import type { RevalidatePayload } from '@vigilkids/cms-client'
import { verifyWebhookSignature } from '@vigilkids/cms-client/webhook'
export function parseCmsWebhook(
rawBody: string,
signature: string,
secret: string,
): RevalidatePayload {
const verified = verifyWebhookSignature({
rawBody,
signature,
secret,
})
if (!verified) {
throw new Error('Invalid CMS webhook signature')
}
return JSON.parse(rawBody) as RevalidatePayload
}Client Methods
| Area | Methods |
|------|---------|
| Articles | getArticles, getArticle, getRelatedArticles, searchArticles |
| Authors | getAuthorsPage, getAuthors, getAuthor, getAuthorArticlesPage, getAuthorArticles |
| Categories | getCategories |
| Comments | getComments, createComment |
| Sitemap, redirects, series | getSitemap, getRedirects, getSeries |
Exports
| Entry Point | Import | Content |
|-------------|--------|---------|
| Main | @vigilkids/cms-client | CmsClient, createCmsClient, CmsApiError, CmsClientConfig, and all public request/response types |
| Types | @vigilkids/cms-client/types | Public CMS request/response type definitions |
| Webhook | @vigilkids/cms-client/webhook | verifyWebhookSignature and VerifyWebhookOptions |
Error Handling
CmsApiError is thrown for non-2xx API responses.
import { CmsApiError, createCmsClient } from '@vigilkids/cms-client'
const cms = createCmsClient({
baseUrl: 'https://api.example.com/api/v1/cms',
})
export async function loadRequiredArticle(slug: string): Promise<string> {
try {
const article = await cms.getArticle(slug)
return article.title
}
catch (error) {
if (error instanceof CmsApiError && error.isNotFound) {
return 'Article not found'
}
throw error
}
}Compatibility
- ESM package.
- Main client requires a fetch-compatible runtime. Node.js 18+ provides
globalThis.fetch; other runtimes can passfetchin the client configuration. @vigilkids/cms-client/webhookuses Node.jscryptoandBuffer, so signature verification should run in a server runtime.- TypeScript declarations are included with the package.
