Skip to content

Commit 2bc8666

Browse files
authored
feat(plugin-search)!: make search collection fields override into a function that provides defaultFields inline with other plugins (#7095)
searchPlugin's searchOverrides for the collection now takes in a fields function instead of array similar to other plugins and patterns we use to allow you to map over existing fields as well if needed. ```ts // before searchPlugin({ searchOverrides: { slug: 'search-results', fields: [ { name: 'excerpt', type: 'textarea', admin: { position: 'sidebar', }, }, ] }, }), // current searchPlugin({ searchOverrides: { slug: 'search-results', fields: ({ defaultFields }) => [ ...defaultFields, { name: 'excerpt', type: 'textarea', admin: { position: 'sidebar', }, }, ] }, }), ```
1 parent 8ea87af commit 2bc8666

File tree

4 files changed

+94
-62
lines changed

4 files changed

+94
-62
lines changed

docs/plugins/search.mdx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,25 @@ The `defaultPriorities` property is used to set a fallback `priority` on search
104104

105105
This plugin automatically creates the `search` collection, but you can override anything on this collection via the `searchOverrides` property. It accepts anything from the [Payload Collection Config](https://payloadcms.com/docs/configuration/collections) and merges it in with the default `search` collection config provided by the plugin.
106106

107+
Note that the `fields` property is a function that receives an object with a `defaultFields` key. This is an array of fields that are automatically added to the `search` collection. You can modify this array or add new fields to it.
108+
107109
```ts
108110
// payload.config.ts
109111
{
110112
// ...
111113
searchPlugin({
112114
searchOverrides: {
113115
slug: 'search-results',
116+
fields: ({ defaultFields }) => [
117+
...defaultFields,
118+
{
119+
name: 'excerpt',
120+
type: 'textarea',
121+
admin: {
122+
position: 'sidebar',
123+
},
124+
},
125+
],
114126
},
115127
}),
116128
}
Lines changed: 66 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { CollectionConfig } from 'payload'
1+
import type { CollectionConfig, Field } from 'payload'
22

33
import deepMerge from 'deepmerge'
44

@@ -7,63 +7,75 @@ import type { SearchPluginConfig } from '../types.js'
77
import { LinkToDoc } from './ui/index.js'
88

99
// all settings can be overridden by the config
10-
export const generateSearchCollection = (pluginConfig: SearchPluginConfig): CollectionConfig =>
11-
deepMerge(
10+
export const generateSearchCollection = (pluginConfig: SearchPluginConfig): CollectionConfig => {
11+
const defaultFields: Field[] = [
1212
{
13-
slug: 'search',
14-
access: {
15-
create: (): boolean => false,
16-
read: (): boolean => true,
13+
name: 'title',
14+
type: 'text',
15+
admin: {
16+
readOnly: true,
1717
},
18+
},
19+
{
20+
name: 'priority',
21+
type: 'number',
1822
admin: {
19-
defaultColumns: ['title'],
20-
description:
21-
'This is a collection of automatically created search results. These results are used by the global site search and will be updated automatically as documents in the CMS are created or updated.',
22-
enableRichTextRelationship: false,
23-
useAsTitle: 'title',
23+
position: 'sidebar',
2424
},
25-
fields: [
26-
{
27-
name: 'title',
28-
type: 'text',
29-
admin: {
30-
readOnly: true,
31-
},
32-
},
33-
{
34-
name: 'priority',
35-
type: 'number',
36-
admin: {
37-
position: 'sidebar',
38-
},
39-
},
40-
{
41-
name: 'doc',
42-
type: 'relationship',
43-
admin: {
44-
position: 'sidebar',
45-
readOnly: true,
46-
},
47-
index: true,
48-
maxDepth: 0,
49-
relationTo: pluginConfig?.collections || [],
50-
required: true,
51-
},
52-
{
53-
name: 'docUrl',
54-
type: 'ui',
55-
admin: {
56-
components: {
57-
Field: LinkToDoc,
58-
},
59-
position: 'sidebar',
60-
},
25+
},
26+
{
27+
name: 'doc',
28+
type: 'relationship',
29+
admin: {
30+
position: 'sidebar',
31+
readOnly: true,
32+
},
33+
index: true,
34+
maxDepth: 0,
35+
relationTo: pluginConfig?.collections || [],
36+
required: true,
37+
},
38+
{
39+
name: 'docUrl',
40+
type: 'ui',
41+
admin: {
42+
components: {
43+
Field: LinkToDoc,
6144
},
62-
],
63-
labels: {
64-
plural: 'Search Results',
65-
singular: 'Search Result',
45+
position: 'sidebar',
6646
},
6747
},
68-
pluginConfig?.searchOverrides || {},
69-
)
48+
]
49+
50+
const newConfig: CollectionConfig = {
51+
...(pluginConfig?.searchOverrides || {}),
52+
slug: pluginConfig?.searchOverrides?.slug || 'search',
53+
access: {
54+
create: (): boolean => false,
55+
read: (): boolean => true,
56+
...(pluginConfig?.searchOverrides?.access || {}),
57+
},
58+
admin: {
59+
defaultColumns: ['title'],
60+
description:
61+
'This is a collection of automatically created search results. These results are used by the global site search and will be updated automatically as documents in the CMS are created or updated.',
62+
enableRichTextRelationship: false,
63+
useAsTitle: 'title',
64+
...(pluginConfig?.searchOverrides?.admin || {}),
65+
},
66+
fields:
67+
pluginConfig?.searchOverrides?.fields &&
68+
typeof pluginConfig?.searchOverrides?.fields === 'function'
69+
? pluginConfig?.searchOverrides.fields({ defaultFields })
70+
: defaultFields,
71+
hooks: {
72+
...(pluginConfig?.searchOverrides?.hooks || {}),
73+
},
74+
labels: {
75+
plural: 'Search Results',
76+
singular: 'Search Result',
77+
},
78+
}
79+
80+
return newConfig
81+
}

packages/plugin-search/src/types.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import type { CollectionAfterChangeHook, CollectionConfig, Payload, PayloadRequest } from 'payload'
1+
import type {
2+
CollectionAfterChangeHook,
3+
CollectionConfig,
4+
Field,
5+
Payload,
6+
PayloadRequest,
7+
} from 'payload'
28

39
export type DocToSync = {
410
[key: string]: any
@@ -18,22 +24,24 @@ export type BeforeSync = (args: {
1824
searchDoc: DocToSync
1925
}) => DocToSync | Promise<DocToSync>
2026

27+
export type FieldsOverride = (args: { defaultFields: Field[] }) => Field[]
28+
2129
export type SearchPluginConfig = {
2230
beforeSync?: BeforeSync
2331
collections?: string[]
2432
defaultPriorities?: {
2533
[collection: string]: ((doc: any) => Promise<number> | number) | number
2634
}
2735
deleteDrafts?: boolean
28-
searchOverrides?: Partial<CollectionConfig>
36+
searchOverrides?: { fields?: FieldsOverride } & Partial<Omit<CollectionConfig, 'fields'>>
2937
syncDrafts?: boolean
3038
}
3139

3240
// Extend the `CollectionAfterChangeHook` with more function args
3341
// Convert the `collection` arg from `SanitizedCollectionConfig` to a string
3442
export type SyncWithSearch = (
35-
Args: Omit<Parameters<CollectionAfterChangeHook>[0], 'collection'> & {
43+
Args: {
3644
collection: string
3745
pluginConfig: SearchPluginConfig
38-
},
46+
} & Omit<Parameters<CollectionAfterChangeHook>[0], 'collection'>,
3947
) => ReturnType<CollectionAfterChangeHook>

test/plugin-search/config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ export default buildConfigWithDefaults({
4141
posts: ({ title }) => (title === 'Hello, world!' ? 30 : 20),
4242
},
4343
searchOverrides: {
44-
fields: [
44+
fields: ({ defaultFields }) => [
45+
...defaultFields,
4546
{
4647
name: 'excerpt',
47-
type: 'text',
48+
type: 'textarea',
4849
admin: {
49-
readOnly: true,
50+
position: 'sidebar',
5051
},
51-
label: 'Excerpt',
5252
},
5353
],
5454
},

0 commit comments

Comments
 (0)