Skip to content

Commit c41ef65

Browse files
authored
feat: add defaultPopulate property to collection config (#8934)
### What? Adds `defaultPopulate` property to collection config that allows to specify which fields to select when the collection is populated from another document. ```ts import type { CollectionConfig } from 'payload' // The TSlug generic can be passed to have type safety for `defaultPopulate`. // If avoided, the `defaultPopulate` type resolves to `SelectType`. export const Pages: CollectionConfig<'pages'> = { slug: 'pages', // I need only slug, NOT the WHOLE CONTENT! defaultPopulate: { slug: true, }, fields: [ { name: 'slug', type: 'text', required: true, }, ], } ``` ### Why? This is essential for example in case of links. You don't need the whole document, which can contain large data but only the `slug`. ### How? Implements `defaultPopulate` when populating relationships, including inside of lexical / slate rich text fields.
1 parent d38d7b8 commit c41ef65

File tree

15 files changed

+375
-5
lines changed

15 files changed

+375
-5
lines changed

docs/configuration/collections.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export const Posts: CollectionConfig = {
5858
The following options are available:
5959

6060
| Option | Description |
61-
|------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
61+
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
6262
| **`admin`** | The configuration options for the Admin Panel. [More details](../admin/collections). |
6363
| **`access`** | Provide Access Control functions to define exactly who should be able to do what with Documents in this Collection. [More details](../access-control/collections). |
6464
| **`auth`** | Specify options if you would like this Collection to feature authentication. [More details](../authentication/overview). |
@@ -77,6 +77,7 @@ The following options are available:
7777
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
7878
| **`upload`** | Specify options if you would like this Collection to support file uploads. For more, consult the [Uploads](../upload/overview) documentation. |
7979
| **`versions`** | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#collection-config). |
80+
| **`defaultPopulate`** | Specify which fields to select when this Collection is populated from another document. [More Details](../queries/select#defaultpopulate-collection-config-property). |
8081

8182
_\* An asterisk denotes that a property is required._
8283

docs/queries/select.mdx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,34 @@ const getPosts = async () => {
9797
<strong>Reminder:</strong>
9898
This is the same for [Globals](../configuration/globals) using the `/api/globals` endpoint.
9999
</Banner>
100+
```
101+
102+
103+
## `defaultPopulate` collection config property
104+
105+
The `defaultPopulate` property allows you specify which fields to select when populating the collection from another document.
106+
This is especially useful for links where only the `slug` is needed instead of the entire document.
107+
108+
```ts
109+
import type { CollectionConfig } from 'payload'
110+
111+
import { lexicalEditor, LinkFeature } from '@payloadcms/richtext-lexical'
112+
import { slateEditor } from '@payloadcms/richtext-slate'
113+
114+
// The TSlug generic can be passed to have type safety for `defaultPopulate`.
115+
// If avoided, the `defaultPopulate` type resolves to `SelectType`.
116+
export const Pages: CollectionConfig<'pages'> = {
117+
slug: 'pages',
118+
// Specify `select`.
119+
defaultPopulate: {
120+
slug: true,
121+
},
122+
fields: [
123+
{
124+
name: 'slug',
125+
type: 'text',
126+
required: true,
127+
},
128+
],
129+
}
130+
```

packages/payload/src/collections/config/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { GraphQLInputObjectType, GraphQLNonNull, GraphQLObjectType } from 'graphql'
2-
import type { DeepRequired, MarkOptional } from 'ts-essentials'
2+
import type { DeepRequired, IsAny, MarkOptional } from 'ts-essentials'
33

44
import type {
55
CustomPreviewButton,
@@ -382,6 +382,9 @@ export type CollectionConfig<TSlug extends CollectionSlug = any> = {
382382
* @WARNING: If you change this property with existing data, you will need to handle the renaming of the table in your database or by using migrations
383383
*/
384384
dbName?: DBIdentifierName
385+
defaultPopulate?: IsAny<SelectFromCollectionSlug<TSlug>> extends true
386+
? SelectType
387+
: SelectFromCollectionSlug<TSlug>
385388
/**
386389
* Default field to sort by in collection list view
387390
*/

packages/payload/src/collections/dataloader.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { BatchLoadFn } from 'dataloader'
22

33
import DataLoader from 'dataloader'
44

5-
import type { PayloadRequest } from '../types/index.js'
5+
import type { PayloadRequest, SelectType } from '../types/index.js'
66
import type { TypeWithID } from './config/types.js'
77

88
import { isValidID } from '../utilities/isValidID.js'
@@ -55,6 +55,7 @@ const batchAndLoadDocs =
5555
overrideAccess,
5656
showHiddenFields,
5757
draft,
58+
select,
5859
] = JSON.parse(key)
5960

6061
const batchKeyArray = [
@@ -67,6 +68,7 @@ const batchAndLoadDocs =
6768
overrideAccess,
6869
showHiddenFields,
6970
draft,
71+
select,
7072
]
7173

7274
const batchKey = JSON.stringify(batchKeyArray)
@@ -103,6 +105,7 @@ const batchAndLoadDocs =
103105
overrideAccess,
104106
showHiddenFields,
105107
draft,
108+
select,
106109
] = JSON.parse(batchKey)
107110

108111
req.transactionID = transactionID
@@ -118,6 +121,7 @@ const batchAndLoadDocs =
118121
overrideAccess: Boolean(overrideAccess),
119122
pagination: false,
120123
req,
124+
select,
121125
showHiddenFields: Boolean(showHiddenFields),
122126
where: {
123127
id: {
@@ -139,6 +143,7 @@ const batchAndLoadDocs =
139143
fallbackLocale,
140144
locale,
141145
overrideAccess,
146+
select,
142147
showHiddenFields,
143148
transactionID: req.transactionID,
144149
})
@@ -167,6 +172,7 @@ type CreateCacheKeyArgs = {
167172
fallbackLocale: string
168173
locale: string
169174
overrideAccess: boolean
175+
select?: SelectType
170176
showHiddenFields: boolean
171177
transactionID: number | Promise<number | string> | string
172178
}
@@ -179,6 +185,7 @@ export const createDataloaderCacheKey = ({
179185
fallbackLocale,
180186
locale,
181187
overrideAccess,
188+
select,
182189
showHiddenFields,
183190
transactionID,
184191
}: CreateCacheKeyArgs): string =>
@@ -193,4 +200,5 @@ export const createDataloaderCacheKey = ({
193200
overrideAccess,
194201
showHiddenFields,
195202
draft,
203+
select,
196204
])

packages/payload/src/fields/hooks/afterRead/relationshipPopulationPromise.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const populate = async ({
6969
fallbackLocale,
7070
locale,
7171
overrideAccess,
72+
select: relatedCollection.config.defaultPopulate,
7273
showHiddenFields,
7374
transactionID: req.transactionID,
7475
}),

packages/richtext-lexical/src/features/relationship/server/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export const RelationshipFeature = createServerFeature<
9090
key: 'value',
9191
overrideAccess,
9292
req,
93+
select: collection.config.defaultPopulate,
9394
showHiddenFields,
9495
}),
9596
)

packages/richtext-lexical/src/features/upload/server/feature.server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ export const UploadFeature = createServerFeature<
261261
key: 'value',
262262
overrideAccess,
263263
req,
264+
select: collection.config.defaultPopulate,
264265
showHiddenFields,
265266
}),
266267
)

packages/richtext-lexical/src/populateGraphQL/populate.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { PayloadRequest } from 'payload'
1+
import type { PayloadRequest, SelectType } from 'payload'
22

33
import { createDataloaderCacheKey } from 'payload'
44

@@ -10,6 +10,7 @@ type Arguments = {
1010
key: number | string
1111
overrideAccess: boolean
1212
req: PayloadRequest
13+
select?: SelectType
1314
showHiddenFields: boolean
1415
}
1516

@@ -23,6 +24,7 @@ export const populate = async ({
2324
key,
2425
overrideAccess,
2526
req,
27+
select,
2628
showHiddenFields,
2729
}: {
2830
collectionSlug: string
@@ -46,6 +48,7 @@ export const populate = async ({
4648
fallbackLocale: req.fallbackLocale!,
4749
locale: req.locale!,
4850
overrideAccess,
51+
select,
4952
showHiddenFields,
5053
transactionID: req.transactionID!,
5154
}),

packages/richtext-slate/src/data/populate.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Collection, Field, PayloadRequest, RichTextField } from 'payload'
1+
import type { Collection, Field, PayloadRequest, RichTextField, SelectType } from 'payload'
22

33
import { createDataloaderCacheKey } from 'payload'
44

@@ -13,6 +13,7 @@ type Arguments = {
1313
key: number | string
1414
overrideAccess?: boolean
1515
req: PayloadRequest
16+
select?: SelectType
1617
showHiddenFields: boolean
1718
}
1819

@@ -26,6 +27,7 @@ export const populate = async ({
2627
key,
2728
overrideAccess,
2829
req,
30+
select,
2931
showHiddenFields,
3032
}: {
3133
collection: Collection
@@ -44,6 +46,7 @@ export const populate = async ({
4446
fallbackLocale: req.locale,
4547
locale: req.fallbackLocale,
4648
overrideAccess: typeof overrideAccess === 'undefined' ? false : overrideAccess,
49+
select,
4750
showHiddenFields,
4851
transactionID: req.transactionID,
4952
}),

packages/richtext-slate/src/data/recurseNestedFields.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export const recurseNestedFields = ({
4848
key: i,
4949
overrideAccess,
5050
req,
51+
select: collection.config.defaultPopulate,
5152
showHiddenFields,
5253
}),
5354
)
@@ -69,6 +70,7 @@ export const recurseNestedFields = ({
6970
key: i,
7071
overrideAccess,
7172
req,
73+
select: collection.config.defaultPopulate,
7274
showHiddenFields,
7375
}),
7476
)
@@ -94,6 +96,7 @@ export const recurseNestedFields = ({
9496
key: 'value',
9597
overrideAccess,
9698
req,
99+
select: collection.config.defaultPopulate,
97100
showHiddenFields,
98101
}),
99102
)
@@ -114,6 +117,7 @@ export const recurseNestedFields = ({
114117
key: field.name,
115118
overrideAccess,
116119
req,
120+
select: collection.config.defaultPopulate,
117121
showHiddenFields,
118122
}),
119123
)

0 commit comments

Comments
 (0)