fix: populate is ignored for nested relationships (#11227)
### What? As described in https://github.com/payloadcms/payload/issues/11209, previously, the `populate` argument was ignored for nested relationships. ### Why? `populate` should work for nested relationships, no matter where they are in the tree. ### How? Preserves the `populate` argument in the payload data loader. Fixes https://github.com/payloadcms/payload/issues/11209
This commit is contained in:
@@ -3,7 +3,7 @@ import type { BatchLoadFn } from 'dataloader'
|
||||
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
import type { PayloadRequest, SelectType } from '../types/index.js'
|
||||
import type { PayloadRequest, PopulateType, SelectType } from '../types/index.js'
|
||||
import type { TypeWithID } from './config/types.js'
|
||||
|
||||
import { isValidID } from '../utilities/isValidID.js'
|
||||
@@ -57,6 +57,7 @@ const batchAndLoadDocs =
|
||||
showHiddenFields,
|
||||
draft,
|
||||
select,
|
||||
populate,
|
||||
] = JSON.parse(key)
|
||||
|
||||
const batchKeyArray = [
|
||||
@@ -70,6 +71,7 @@ const batchAndLoadDocs =
|
||||
showHiddenFields,
|
||||
draft,
|
||||
select,
|
||||
populate,
|
||||
]
|
||||
|
||||
const batchKey = JSON.stringify(batchKeyArray)
|
||||
@@ -107,6 +109,7 @@ const batchAndLoadDocs =
|
||||
showHiddenFields,
|
||||
draft,
|
||||
select,
|
||||
populate,
|
||||
] = JSON.parse(batchKey)
|
||||
|
||||
req.transactionID = transactionID
|
||||
@@ -121,6 +124,7 @@ const batchAndLoadDocs =
|
||||
locale,
|
||||
overrideAccess: Boolean(overrideAccess),
|
||||
pagination: false,
|
||||
populate,
|
||||
req,
|
||||
select,
|
||||
showHiddenFields: Boolean(showHiddenFields),
|
||||
@@ -144,6 +148,7 @@ const batchAndLoadDocs =
|
||||
fallbackLocale,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populate,
|
||||
select,
|
||||
showHiddenFields,
|
||||
transactionID: req.transactionID,
|
||||
@@ -173,6 +178,7 @@ type CreateCacheKeyArgs = {
|
||||
fallbackLocale: string
|
||||
locale: string
|
||||
overrideAccess: boolean
|
||||
populate?: PopulateType
|
||||
select?: SelectType
|
||||
showHiddenFields: boolean
|
||||
transactionID: number | Promise<number | string> | string
|
||||
@@ -186,6 +192,7 @@ export const createDataloaderCacheKey = ({
|
||||
fallbackLocale,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populate,
|
||||
select,
|
||||
showHiddenFields,
|
||||
transactionID,
|
||||
@@ -202,4 +209,5 @@ export const createDataloaderCacheKey = ({
|
||||
showHiddenFields,
|
||||
draft,
|
||||
select,
|
||||
populate,
|
||||
])
|
||||
|
||||
@@ -72,6 +72,7 @@ const populate = async ({
|
||||
fallbackLocale,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populate: populateArg,
|
||||
select:
|
||||
populateArg?.[relatedCollection.config.slug] ??
|
||||
relatedCollection.config.defaultPopulate,
|
||||
|
||||
@@ -21,6 +21,11 @@ export const Pages: CollectionConfig<'pages'> = {
|
||||
},
|
||||
access: { read: () => true },
|
||||
fields: [
|
||||
{
|
||||
name: 'relatedPage',
|
||||
type: 'relationship',
|
||||
relationTo: 'pages',
|
||||
},
|
||||
{
|
||||
name: 'content',
|
||||
type: 'blocks',
|
||||
|
||||
@@ -2230,6 +2230,33 @@ describe('Select', () => {
|
||||
expect(richTextLexicalRel.value).toMatchObject(expectedHomePageOverride)
|
||||
expect(richTextSlateRel.value).toMatchObject(expectedHomePageOverride)
|
||||
})
|
||||
|
||||
it('should apply populate on depth 2', async () => {
|
||||
const page_1 = await payload.create({
|
||||
collection: 'pages',
|
||||
data: { relatedPage: null, blocks: [{ blockType: 'some' }], slug: 'page-1' },
|
||||
})
|
||||
const page_2 = await payload.create({
|
||||
collection: 'pages',
|
||||
data: { relatedPage: page_1.id, slug: 'page-2' },
|
||||
})
|
||||
const page_3 = await payload.create({
|
||||
collection: 'pages',
|
||||
data: { relatedPage: page_2.id, slug: 'page-3' },
|
||||
})
|
||||
const result = await payload.findByID({
|
||||
collection: 'pages',
|
||||
id: page_3.id,
|
||||
depth: 3,
|
||||
populate: { pages: { slug: true, relatedPage: true } },
|
||||
})
|
||||
expect(result.relatedPage.id).toBe(page_2.id)
|
||||
expect(result.relatedPage.relatedPage as Page).toStrictEqual({
|
||||
id: page_1.id,
|
||||
slug: page_1.slug,
|
||||
relatedPage: null,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -6,10 +6,65 @@
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supported timezones in IANA format.
|
||||
*
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "supportedTimezones".
|
||||
*/
|
||||
export type SupportedTimezones =
|
||||
| 'Pacific/Midway'
|
||||
| 'Pacific/Niue'
|
||||
| 'Pacific/Honolulu'
|
||||
| 'Pacific/Rarotonga'
|
||||
| 'America/Anchorage'
|
||||
| 'Pacific/Gambier'
|
||||
| 'America/Los_Angeles'
|
||||
| 'America/Tijuana'
|
||||
| 'America/Denver'
|
||||
| 'America/Phoenix'
|
||||
| 'America/Chicago'
|
||||
| 'America/Guatemala'
|
||||
| 'America/New_York'
|
||||
| 'America/Bogota'
|
||||
| 'America/Caracas'
|
||||
| 'America/Santiago'
|
||||
| 'America/Buenos_Aires'
|
||||
| 'America/Sao_Paulo'
|
||||
| 'Atlantic/South_Georgia'
|
||||
| 'Atlantic/Azores'
|
||||
| 'Atlantic/Cape_Verde'
|
||||
| 'Europe/London'
|
||||
| 'Europe/Berlin'
|
||||
| 'Africa/Lagos'
|
||||
| 'Europe/Athens'
|
||||
| 'Africa/Cairo'
|
||||
| 'Europe/Moscow'
|
||||
| 'Asia/Riyadh'
|
||||
| 'Asia/Dubai'
|
||||
| 'Asia/Baku'
|
||||
| 'Asia/Karachi'
|
||||
| 'Asia/Tashkent'
|
||||
| 'Asia/Calcutta'
|
||||
| 'Asia/Dhaka'
|
||||
| 'Asia/Almaty'
|
||||
| 'Asia/Jakarta'
|
||||
| 'Asia/Bangkok'
|
||||
| 'Asia/Shanghai'
|
||||
| 'Asia/Singapore'
|
||||
| 'Asia/Tokyo'
|
||||
| 'Asia/Seoul'
|
||||
| 'Australia/Sydney'
|
||||
| 'Pacific/Guam'
|
||||
| 'Pacific/Noumea'
|
||||
| 'Pacific/Auckland'
|
||||
| 'Pacific/Fiji';
|
||||
|
||||
export interface Config {
|
||||
auth: {
|
||||
users: UserAuthOperations;
|
||||
};
|
||||
blocks: {};
|
||||
collections: {
|
||||
posts: Post;
|
||||
'localized-posts': LocalizedPost;
|
||||
@@ -122,7 +177,7 @@ export interface Post {
|
||||
unnamedTabNumber?: number | null;
|
||||
hasOne?: (string | null) | Rel;
|
||||
hasMany?: (string | Rel)[] | null;
|
||||
hasManyUpload?: (string | Rel)[] | null;
|
||||
hasManyUpload?: (string | Upload)[] | null;
|
||||
hasOnePoly?: {
|
||||
relationTo: 'rels';
|
||||
value: string | Rel;
|
||||
@@ -145,6 +200,24 @@ export interface Rel {
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "upload".
|
||||
*/
|
||||
export interface Upload {
|
||||
id: string;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
url?: string | null;
|
||||
thumbnailURL?: string | null;
|
||||
filename?: string | null;
|
||||
mimeType?: string | null;
|
||||
filesize?: number | null;
|
||||
width?: number | null;
|
||||
height?: number | null;
|
||||
focalX?: number | null;
|
||||
focalY?: number | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "localized-posts".
|
||||
@@ -290,6 +363,7 @@ export interface DeepPost {
|
||||
*/
|
||||
export interface Page {
|
||||
id: string;
|
||||
relatedPage?: (string | null) | Page;
|
||||
content?:
|
||||
| {
|
||||
title: string;
|
||||
@@ -369,24 +443,6 @@ export interface Point {
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "upload".
|
||||
*/
|
||||
export interface Upload {
|
||||
id: string;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
url?: string | null;
|
||||
thumbnailURL?: string | null;
|
||||
filename?: string | null;
|
||||
mimeType?: string | null;
|
||||
filesize?: number | null;
|
||||
width?: number | null;
|
||||
height?: number | null;
|
||||
focalX?: number | null;
|
||||
focalY?: number | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
@@ -706,6 +762,7 @@ export interface DeepPostsSelect<T extends boolean = true> {
|
||||
* via the `definition` "pages_select".
|
||||
*/
|
||||
export interface PagesSelect<T extends boolean = true> {
|
||||
relatedPage?: T;
|
||||
content?:
|
||||
| T
|
||||
| {
|
||||
|
||||
Reference in New Issue
Block a user