Skip to content

Commit a6ffbc5

Browse files
feat: enhance filtering capabilities with operation-level and field-level options
1 parent 0b8da84 commit a6ffbc5

File tree

8 files changed

+2182
-1076
lines changed

8 files changed

+2182
-1076
lines changed

README.md

Lines changed: 159 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Autogenerate an OpenAPI specification from your Payload CMS instance and use it
1414
- [x] Support Payload CMS 3.x
1515
- [x] Support generating both OpenAPI 3.0 and 3.1
1616
- [x] Collection and Global filtering options
17+
- [x] Operation-level filtering (CRUD operations)
18+
- [x] Field-level filtering
1719
- [ ] Custom endpoints
1820

1921
# Installation
@@ -72,64 +74,197 @@ buildConfig({
7274
})
7375
```
7476

75-
## 3. Filtering Collections and Globals (optional)
77+
## 3. Filtering and Control Options
7678

77-
You can control which collections and globals are included in the OpenAPI specification using filtering options:
79+
### Collection and Global Filtering
7880

79-
### Include/Exclude by slug
81+
Control which collections and globals are included in the OpenAPI specification:
8082

8183
```typescript
8284
import { openapi } from 'payload-oapi'
8385

86+
// Basic filtering with arrays
8487
buildConfig({
8588
plugins: [
8689
openapi({
8790
openapiVersion: '3.0',
88-
metadata: { title: 'Dev API', version: '0.0.1' },
89-
// Only include specific collections
90-
includeCollections: ['posts', 'users'],
91-
// Exclude specific globals
91+
metadata: { title: 'Public API', version: '1.0.0' },
92+
93+
// Include only specific collections
94+
includeCollections: ['posts', 'categories'],
95+
96+
// Exclude sensitive globals
9297
excludeGlobals: ['internal-settings'],
98+
99+
// Hide internal Payload collections (payload-preferences, payload-migrations)
100+
hideInternalCollections: true,
101+
}),
102+
],
103+
})
104+
105+
// Advanced filtering with functions
106+
buildConfig({
107+
plugins: [
108+
openapi({
109+
openapiVersion: '3.0',
110+
metadata: { title: 'Public API', version: '1.0.0' },
111+
112+
// Custom filtering with functions
113+
includeCollections: ({ slug, config }) => {
114+
return config.auth || config.access?.read === true
115+
},
116+
117+
excludeGlobals: ({ slug, config }) => {
118+
return slug.startsWith('internal-')
119+
},
93120
}),
94121
],
95-
// ...
96122
})
97123
```
98124

99-
### Custom filtering functions
125+
### Operation-Level Filtering
126+
127+
Control which CRUD operations are included for collections:
100128

101129
```typescript
102130
import { openapi } from 'payload-oapi'
103131

132+
// Include only specific operations
104133
buildConfig({
105134
plugins: [
106135
openapi({
107136
openapiVersion: '3.0',
108-
metadata: { title: 'Dev API', version: '0.0.1' },
109-
// Include collections based on custom logic
110-
includeCollections: ({ slug, config }) => {
111-
// Only include collections that have auth enabled or are public
112-
return config.auth || config.access?.read === true
137+
metadata: { title: 'Read-Only API', version: '1.0.0' },
138+
139+
operations: {
140+
includeOperations: ['read', 'list'],
113141
},
114-
// Exclude globals based on custom logic
115-
excludeGlobals: ({ slug }) => {
116-
// Exclude any globals that start with 'internal-'
117-
return slug.startsWith('internal-')
142+
}),
143+
],
144+
})
145+
146+
// Exclude dangerous operations
147+
buildConfig({
148+
plugins: [
149+
openapi({
150+
openapiVersion: '3.0',
151+
metadata: { title: 'Safe API', version: '1.0.0' },
152+
153+
operations: {
154+
excludeOperations: ['delete'],
155+
},
156+
}),
157+
],
158+
})
159+
160+
// Custom operation filtering per collection
161+
buildConfig({
162+
plugins: [
163+
openapi({
164+
openapiVersion: '3.0',
165+
metadata: { title: 'Custom API', version: '1.0.0' },
166+
167+
operations: {
168+
operationFilter: (operation, collection) => {
169+
// Only allow read operations for sensitive collections
170+
if (collection.slug === 'users') {
171+
return ['read', 'list'].includes(operation)
172+
}
173+
// Allow all operations for other collections
174+
return true
175+
}
118176
},
119177
}),
120178
],
121-
// ...
122179
})
123180
```
124181

182+
### Field-Level Filtering
183+
184+
Control which fields are exposed in the documentation:
185+
186+
```typescript
187+
import { openapi } from 'payload-oapi'
188+
189+
// Exclude specific fields by name
190+
buildConfig({
191+
plugins: [
192+
openapi({
193+
openapiVersion: '3.0',
194+
metadata: { title: 'Clean API', version: '1.0.0' },
195+
196+
excludeFields: ['internalNotes', 'adminComments'],
197+
}),
198+
],
199+
})
200+
201+
// Custom field filtering by type and name
202+
buildConfig({
203+
plugins: [
204+
openapi({
205+
openapiVersion: '3.0',
206+
metadata: { title: 'Secure API', version: '1.0.0' },
207+
208+
excludeFields: ({ name, type }) => {
209+
// Exclude all password-type fields and internal fields
210+
return type === 'password' || name.startsWith('_')
211+
},
212+
}),
213+
],
214+
})
215+
216+
// Advanced field filtering with collection context
217+
buildConfig({
218+
plugins: [
219+
openapi({
220+
openapiVersion: '3.0',
221+
metadata: { title: 'Context-Aware API', version: '1.0.0' },
222+
223+
excludeFields: ({ name, type, collection }) => {
224+
// Different filtering rules for different collections
225+
if (collection.slug === 'users') {
226+
// For users, exclude sensitive fields
227+
return ['password', 'salt', 'hash', 'resetPasswordToken'].includes(name)
228+
}
229+
230+
if (collection.slug === 'posts') {
231+
// For posts, exclude internal fields and drafts
232+
return name.startsWith('_') || name === 'draft'
233+
}
234+
235+
// For other collections, only exclude password fields
236+
return type === 'password'
237+
},
238+
}),
239+
],
240+
})
241+
```
242+
243+
# Configuration Options Reference
244+
245+
### Basic Options
246+
- `enabled?: boolean` - Enable/disable the plugin
247+
- `openapiVersion?: '3.0' | '3.1'` - OpenAPI specification version
248+
- `specEndpoint?: string` - Endpoint for the OpenAPI spec (default: `/openapi.json`)
249+
- `authEndpoint?: string` - Authentication endpoint (default: `/openapi-auth`)
250+
- `metadata: OpenAPIMetadata` - API metadata (title, version, description)
251+
125252
### Filtering Options
253+
- `includeCollections?: string[] | FilterFunction` - Collections to include
254+
- `excludeCollections?: string[] | FilterFunction` - Collections to exclude
255+
- `includeGlobals?: string[] | FilterFunction` - Globals to include
256+
- `excludeGlobals?: string[] | FilterFunction` - Globals to exclude
257+
- `hideInternalCollections?: boolean` - Hide payload-* collections
258+
259+
### Operation Control
260+
- `operations?.includeOperations?: CRUDOperation[]` - Operations to include
261+
- `operations?.excludeOperations?: CRUDOperation[]` - Operations to exclude
262+
- `operations?.operationFilter?: Function` - Custom operation filtering
126263

127-
- `includeCollections`: Array of collection slugs or a filter function. If specified, only these collections will be included.
128-
- `excludeCollections`: Array of collection slugs or a filter function. These collections will be excluded.
129-
- `includeGlobals`: Array of global slugs or a filter function. If specified, only these globals will be included.
130-
- `excludeGlobals`: Array of global slugs or a filter function. These globals will be excluded.
264+
### Field Control
265+
- `excludeFields?: string[] | FilterFunction` - Fields to exclude
131266

132-
**Note**: Include filters are applied first, then exclude filters. If both are specified, a collection/global must pass both filters to be included.
267+
**Note**: Filters are applied in order: include → exclude. Custom functions take precedence over arrays.
133268

134269
# Usage
135270

0 commit comments

Comments
 (0)