Files
23ff5c49-3ffc-4a02-b409-140…/AGENT.md
“dongming” ed40350aeb first commit
2025-12-28 22:43:26 +08:00

3.5 KiB
Raw Blame History

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 like Posts, Categories, Pages, Media)
  • Type Definitions: src/clientsdk/types.gen.ts (Contains interfaces like Post, Category, Media)
  • Query Serializer: src/clientsdk/querySerializer.ts (Handles nested object serialization for PayloadCMS queries)
  • Client Factory: src/clientsdk/client/index.ts (Use createClient to 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.categories as an array.
    • Correct: post.categories?.[0]?.title
    • Incorrect: post.category.title
  • Media: Images (like heroImage) are objects containing url, alt, and sizes.
    • Example: <img src={post.heroImage?.url} alt={post.heroImage?.alt} />

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_URL in config.ts matches the backend port (default 3000).
  • Empty Results: Check if the X-Tenant-Slug header matches the slug assigned to your content in the CMS admin panel.
  • Nested Query Error: If you see "Deeply-nested arrays/objects arent supported", verify that you are passing the customQuerySerializer to the createClient options.