chore(agent): configure AI agents and tools

Add configuration for BMad, Claude, OpenCode, and other AI agent tools and workflows.
This commit is contained in:
2026-02-11 11:51:23 +08:00
parent 9c2181f743
commit ad8e2e313e
977 changed files with 157625 additions and 0 deletions

View File

@@ -0,0 +1,373 @@
# Field Types Reference
## Core Field Types
### Text Fields
```ts
// Basic text
{ name: 'title', type: 'text', required: true }
// With validation
{
name: 'email',
type: 'text',
validate: (value) => {
if (!value?.includes('@')) return 'Invalid email'
return true
},
}
// With admin config
{
name: 'description',
type: 'textarea',
admin: {
placeholder: 'Enter description...',
description: 'Brief summary',
},
}
```
### Slug Field Helper
Auto-generate URL-safe slugs:
```ts
import { slugField } from '@payloadcms/plugin-seo'
// Or manual implementation
{
name: 'slug',
type: 'text',
unique: true,
index: true,
hooks: {
beforeValidate: [
({ data, operation, originalDoc }) => {
if (operation === 'create' || !originalDoc?.slug) {
return data?.title?.toLowerCase().replace(/\s+/g, '-')
}
return originalDoc.slug
},
],
},
}
```
### Number Fields
```ts
{ name: 'price', type: 'number', min: 0, required: true }
{ name: 'quantity', type: 'number', defaultValue: 1 }
```
### Select Fields
```ts
// Simple select
{
name: 'status',
type: 'select',
options: ['draft', 'published', 'archived'],
defaultValue: 'draft',
}
// With labels
{
name: 'priority',
type: 'select',
options: [
{ label: 'Low', value: 'low' },
{ label: 'Medium', value: 'medium' },
{ label: 'High', value: 'high' },
],
}
// Multi-select
{
name: 'categories',
type: 'select',
hasMany: true,
options: ['tech', 'design', 'marketing'],
}
```
### Checkbox
```ts
{ name: 'featured', type: 'checkbox', defaultValue: false }
```
### Date Fields
```ts
{ name: 'publishedAt', type: 'date' }
// With time
{
name: 'eventDate',
type: 'date',
admin: { date: { pickerAppearance: 'dayAndTime' } },
}
```
## Relationship Fields
### Basic Relationship
```ts
// Single relationship
{
name: 'author',
type: 'relationship',
relationTo: 'users',
required: true,
}
// Multiple relationships (hasMany)
{
name: 'tags',
type: 'relationship',
relationTo: 'tags',
hasMany: true,
}
// Polymorphic (multiple collections)
{
name: 'parent',
type: 'relationship',
relationTo: ['pages', 'posts'],
}
```
### With Filter Options
Dynamically filter available options:
```ts
{
name: 'relatedPosts',
type: 'relationship',
relationTo: 'posts',
hasMany: true,
filterOptions: ({ data }) => ({
// Only show published posts, exclude self
status: { equals: 'published' },
id: { not_equals: data?.id },
}),
}
```
### Join Fields
Reverse relationship lookup (virtual field):
```ts
// In Posts collection
{
name: 'comments',
type: 'join',
collection: 'comments',
on: 'post', // field name in comments that references posts
}
```
## Virtual Fields
Computed fields that don't store data:
```ts
{
name: 'fullName',
type: 'text',
virtual: true,
hooks: {
afterRead: [
({ data }) => `${data?.firstName} ${data?.lastName}`,
],
},
}
```
## Conditional Fields
Show/hide fields based on other values:
```ts
{
name: 'isExternal',
type: 'checkbox',
},
{
name: 'externalUrl',
type: 'text',
admin: {
condition: (data) => data?.isExternal === true,
},
}
```
## Validation
### Custom Validation
```ts
{
name: 'slug',
type: 'text',
validate: (value, { data, operation }) => {
if (!value) return 'Slug is required'
if (!/^[a-z0-9-]+$/.test(value)) {
return 'Slug must be lowercase letters, numbers, and hyphens only'
}
return true
},
}
```
### Async Validation
```ts
{
name: 'username',
type: 'text',
validate: async (value, { payload }) => {
if (!value) return true
const existing = await payload.find({
collection: 'users',
where: { username: { equals: value } },
})
if (existing.docs.length > 0) return 'Username already taken'
return true
},
}
```
## Group Fields
Organize related fields:
```ts
{
name: 'meta',
type: 'group',
fields: [
{ name: 'title', type: 'text' },
{ name: 'description', type: 'textarea' },
],
}
```
## Array Fields
Repeatable sets of fields:
```ts
{
name: 'socialLinks',
type: 'array',
fields: [
{ name: 'platform', type: 'select', options: ['twitter', 'linkedin', 'github'] },
{ name: 'url', type: 'text' },
],
}
```
## Blocks (Polymorphic Content)
Different content types in same array:
```ts
{
name: 'layout',
type: 'blocks',
blocks: [
{
slug: 'hero',
fields: [
{ name: 'heading', type: 'text' },
{ name: 'image', type: 'upload', relationTo: 'media' },
],
},
{
slug: 'content',
fields: [
{ name: 'richText', type: 'richText' },
],
},
],
}
```
## Point (Geolocation)
```ts
{
name: 'location',
type: 'point',
label: 'Location',
}
// Query nearby
await payload.find({
collection: 'stores',
where: {
location: {
near: [-73.935242, 40.730610, 5000], // lng, lat, maxDistance (meters)
},
},
})
```
## Upload Fields
```ts
{
name: 'featuredImage',
type: 'upload',
relationTo: 'media',
required: true,
}
```
## Rich Text
```ts
{
name: 'content',
type: 'richText',
// Lexical editor features configured in payload.config.ts
}
```
## UI Fields (Presentational)
Fields that don't save data:
```ts
// Row layout
{
type: 'row',
fields: [
{ name: 'firstName', type: 'text', admin: { width: '50%' } },
{ name: 'lastName', type: 'text', admin: { width: '50%' } },
],
}
// Tabs
{
type: 'tabs',
tabs: [
{ label: 'Content', fields: [...] },
{ label: 'Meta', fields: [...] },
],
}
// Collapsible
{
type: 'collapsible',
label: 'Advanced Options',
fields: [...],
}
```