Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 203 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ Autogenerate an OpenAPI specification from your Payload CMS instance and use it
- [x] Preferences endpoints
- [x] Support Payload CMS 3.x
- [x] Support generating both OpenAPI 3.0 and 3.1
- [x] Collection and Global filtering options
- [x] Operation-level filtering (CRUD operations)
- [x] Field-level filtering
- [ ] Custom endpoints

# Installation
Expand All @@ -34,7 +37,10 @@ import { openapi } from 'payload-oapi'

buildConfig({
plugins: [
openapi({ openapiVersion: '3.0', metadata: { title: 'Dev API', version: '0.0.1' } }),
openapi({
openapiVersion: '3.0',
metadata: { title: 'Dev API', version: '0.0.1' }
}),
],
// ...
})
Expand Down Expand Up @@ -68,7 +74,201 @@ buildConfig({
})
```

## 3. Filtering and Control Options

### Collection and Global Filtering

Control which collections and globals are included in the OpenAPI specification:

```typescript
import { openapi } from 'payload-oapi'

// Basic filtering with arrays
buildConfig({
plugins: [
openapi({
openapiVersion: '3.0',
metadata: { title: 'Public API', version: '1.0.0' },

// Include only specific collections
includeCollections: ['posts', 'categories'],

// Exclude sensitive globals
excludeGlobals: ['internal-settings'],

// Hide internal Payload collections (payload-preferences, payload-migrations)
hideInternalCollections: true,
}),
],
})

// Advanced filtering with functions
buildConfig({
plugins: [
openapi({
openapiVersion: '3.0',
metadata: { title: 'Public API', version: '1.0.0' },

// Custom filtering with functions
includeCollections: ({ slug, config }) => {
return config.auth || config.access?.read === true
},

excludeGlobals: ({ slug, config }) => {
return slug.startsWith('internal-')
},
}),
],
})
```

### Operation-Level Filtering

Control which CRUD operations are included for collections:

```typescript
import { openapi } from 'payload-oapi'

// Include only specific operations
buildConfig({
plugins: [
openapi({
openapiVersion: '3.0',
metadata: { title: 'Read-Only API', version: '1.0.0' },

operations: {
includeOperations: ['read', 'list'],
},
}),
],
})

// Exclude dangerous operations
buildConfig({
plugins: [
openapi({
openapiVersion: '3.0',
metadata: { title: 'Safe API', version: '1.0.0' },

operations: {
excludeOperations: ['delete'],
},
}),
],
})

// Custom operation filtering per collection
buildConfig({
plugins: [
openapi({
openapiVersion: '3.0',
metadata: { title: 'Custom API', version: '1.0.0' },

operations: {
operationFilter: (operation, collection) => {
// Only allow read operations for sensitive collections
if (collection.slug === 'users') {
return ['read', 'list'].includes(operation)
}
// Allow all operations for other collections
return true
}
},
}),
],
})
```

### Field-Level Filtering

Control which fields are exposed in the documentation:

```typescript
import { openapi } from 'payload-oapi'

// Exclude specific fields by name
buildConfig({
plugins: [
openapi({
openapiVersion: '3.0',
metadata: { title: 'Clean API', version: '1.0.0' },

excludeFields: ['internalNotes', 'adminComments'],
}),
],
})

// Custom field filtering by type and name
buildConfig({
plugins: [
openapi({
openapiVersion: '3.0',
metadata: { title: 'Secure API', version: '1.0.0' },

excludeFields: ({ name, type }) => {
// Exclude all password-type fields and internal fields
return type === 'password' || name.startsWith('_')
},
}),
],
})

// Advanced field filtering with collection context
buildConfig({
plugins: [
openapi({
openapiVersion: '3.0',
metadata: { title: 'Context-Aware API', version: '1.0.0' },

excludeFields: ({ name, type, collection }) => {
// Different filtering rules for different collections
if (collection.slug === 'users') {
// For users, exclude sensitive fields
return ['password', 'salt', 'hash', 'resetPasswordToken'].includes(name)
}

if (collection.slug === 'posts') {
// For posts, exclude internal fields and drafts
return name.startsWith('_') || name === 'draft'
}

// For other collections, only exclude password fields
return type === 'password'
},
}),
],
})
```

# Configuration Options Reference

### Basic Options
- `enabled?: boolean` - Enable/disable the plugin
- `openapiVersion?: '3.0' | '3.1'` - OpenAPI specification version
- `specEndpoint?: string` - Endpoint for the OpenAPI spec (default: `/openapi.json`)
- `authEndpoint?: string` - Authentication endpoint (default: `/openapi-auth`)
- `metadata: OpenAPIMetadata` - API metadata (title, version, description)

### Filtering Options
- `includeCollections?: string[] | FilterFunction` - Collections to include
- `excludeCollections?: string[] | FilterFunction` - Collections to exclude
- `includeGlobals?: string[] | FilterFunction` - Globals to include
- `excludeGlobals?: string[] | FilterFunction` - Globals to exclude
- `hideInternalCollections?: boolean` - Hide payload-* collections

### Operation Control
- `operations?.includeOperations?: CRUDOperation[]` - Operations to include
- `operations?.excludeOperations?: CRUDOperation[]` - Operations to exclude
- `operations?.operationFilter?: Function` - Custom operation filtering

### Field Control
- `excludeFields?: string[] | FilterFunction` - Fields to exclude

**Note**: Filters are applied in order: include → exclude. Custom functions take precedence over arrays.

# Usage

Unless you configured it otherwise, your spec will be accessible via <https://your-payload.com/api/openapi.json>. If you
added a documentation UI, that will be accessible via <https://your-payload.com/api/docs> (this is also configurable).
By default, the following endpoints are available:

- OpenAPI Specification: `https://your-payload.com/api/openapi.json`
- Documentation UI: `https://your-payload.com/api/docs` (only if you enabled the doc plugin)
Loading