3.5 KiB
3.5 KiB
Client SDK Usage Guide
This project uses an auto-generated SDK powered by @hey-api/openapi-ts to interact with the PayloadCMS multi-tenant backend.
SDK Structure
- Core Methods:
src/clientsdk/sdk.gen.ts(Contains classes likePosts,Categories,Pages,Media) - Type Definitions:
src/clientsdk/types.gen.ts(Contains interfaces likePost,Category,Media) - Query Serializer:
src/clientsdk/querySerializer.ts(Handles nested object serialization for PayloadCMS queries) - Client Factory:
src/clientsdk/client/index.ts(UsecreateClientto initialize a client instance)
1. Initialization
You must initialize the client with the correct baseUrl, querySerializer, and tenant headers.
import { createClient } from '../clientsdk/client';
import { customQuerySerializer } from '../clientsdk/querySerializer';
import { TENANT_SLUG, TENANT_API_KEY, API_URL } from '../config';
const client = createClient({
baseUrl: API_URL,
querySerializer: customQuerySerializer, // CRITICAL: Required for nested where queries
headers: {
'X-Tenant-Slug': TENANT_SLUG,
'X-API-Key': TENANT_API_KEY,
},
});
2. Common Operations
Fetching a List (with Sorting & Limits)
import { Posts } from '../clientsdk/sdk.gen';
const response = await Posts.listPosts({
client,
query: {
limit: 10,
sort: '-createdAt', // Prefix with '-' for descending
},
});
// Access the data
const posts = response.data?.docs || [];
Fetching a Single Document by Slug (Filtering)
PayloadCMS uses a specific where query syntax. The customQuerySerializer handles the translation to where[slug][equals]=my-slug.
const response = await Posts.listPosts({
client,
query: {
where: {
slug: {
equals: 'my-article-slug',
},
},
limit: 1,
},
});
const post = response.data?.docs?.[0];
Filtering by Category Slug
const response = await Posts.listPosts({
client,
query: {
where: {
'categories.slug': {
equals: 'news',
},
},
},
});
3. Data Patterns
Relationships
- Categories: In this project, categories are a many-to-many relationship. Always treat
post.categoriesas an array.- Correct:
post.categories?.[0]?.title - Incorrect:
post.category.title
- Correct:
- Media: Images (like
heroImage) are objects containingurl,alt, andsizes.- Example:
<img src={post.heroImage?.url} alt={post.heroImage?.alt} />
- Example:
Rich Text (Lexical)
PayloadCMS provides Lexical rich text. We typically use post.content_html which is pre-rendered to HTML on the server.
- React:
<div dangerouslySetInnerHTML={{ __html: post.content_html }} /> - Vue:
<div v-html="post.content_html" /> - Astro:
<div set:html={post.content_html} />
4. TypeScript Usage
Always use the generated types for better DX and safety.
import type { Post, Category, Media } from '../clientsdk/types.gen';
function formatPost(post: Post) {
return {
title: post.title,
date: new Date(post.createdAt).toLocaleDateString()
};
}
5. Troubleshooting
- CORS Issues: Ensure
API_URLinconfig.tsmatches the backend port (default 3000). - Empty Results: Check if the
X-Tenant-Slugheader matches the slug assigned to your content in the CMS admin panel. - Nested Query Error: If you see "Deeply-nested arrays/objects aren’t supported", verify that you are passing the
customQuerySerializerto thecreateClientoptions.